From ef0317760958d955209751071b8776d18fc18d46 Mon Sep 17 00:00:00 2001 From: bozzelliandrea Date: Sat, 23 Jul 2022 16:51:19 +0200 Subject: [PATCH 1/3] [Plate] Event Implementation * Implemented queue logic for todo and progress state items * Created new overlay popup for todo items --- .../orders/order-new/order-new.component.html | 2 +- src/app/modules/orders/order.ts | 4 +- .../modules/plates/item/item.component.html | 2 +- src/app/modules/plates/item/item.component.ts | 2 +- .../items-overlay.component.html | 25 ++++++ .../items-overlay.component.scss | 76 +++++++++++++++++++ .../items-overlay/items-overlay.component.ts | 22 ++++++ src/app/modules/plates/plate.interface.ts | 1 + .../modules/plates/plate/plate.component.html | 18 ++++- .../modules/plates/plate/plate.component.scss | 18 +++++ .../modules/plates/plate/plate.component.ts | 71 +++++++++++++++-- src/app/modules/plates/plates.module.ts | 10 ++- .../plates/plates/plates.component.html | 1 + .../modules/plates/plates/plates.component.ts | 6 +- .../services/plate-queue-manager.service.ts | 12 ++- .../modules/shared/class/reactive-queue.ts | 10 ++- .../navbar-button/navbar-button.component.ts | 14 ++-- .../components/navbar/navbar.component.html | 4 + .../components/navbar/navbar.component.ts | 5 ++ src/app/modules/shared/shared.module.ts | 4 +- src/assets/i18n-ita.ts | 6 ++ 21 files changed, 287 insertions(+), 26 deletions(-) create mode 100644 src/app/modules/plates/items-overlay/items-overlay.component.html create mode 100644 src/app/modules/plates/items-overlay/items-overlay.component.scss create mode 100644 src/app/modules/plates/items-overlay/items-overlay.component.ts diff --git a/src/app/modules/orders/order-new/order-new.component.html b/src/app/modules/orders/order-new/order-new.component.html index d6a50d7..4eec53e 100644 --- a/src/app/modules/orders/order-new/order-new.component.html +++ b/src/app/modules/orders/order-new/order-new.component.html @@ -16,7 +16,7 @@
-
- panino + {{config.name}} ordine 10
    diff --git a/src/app/modules/plates/item/item.component.ts b/src/app/modules/plates/item/item.component.ts index 90f01a0..dfed982 100644 --- a/src/app/modules/plates/item/item.component.ts +++ b/src/app/modules/plates/item/item.component.ts @@ -25,7 +25,7 @@ export class ItemComponent { const event: ItemEvent = { action: Status.Cancelled, item: this.config - }; + } as ItemEvent; //TODO: Handle moved or re-queued reasons diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.html b/src/app/modules/plates/items-overlay/items-overlay.component.html new file mode 100644 index 0000000..380cb80 --- /dev/null +++ b/src/app/modules/plates/items-overlay/items-overlay.component.html @@ -0,0 +1,25 @@ +
    + +

    Ordini in Attesa

    +
    +
    + + {{i.name}} + ORDINE + +
    +
    +
    + +

    {{i18n.PLATE.OVERLAY.EMPTY}}

    +
    +
    diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.scss b/src/app/modules/plates/items-overlay/items-overlay.component.scss new file mode 100644 index 0000000..81999f8 --- /dev/null +++ b/src/app/modules/plates/items-overlay/items-overlay.component.scss @@ -0,0 +1,76 @@ +@import "mixins"; + +section { + width: 97%; + height: 200px; + + margin: auto; + + background-color: white; + overflow-y: auto; + overflow-x: hidden; + + border: 1px solid white; + border-radius: 5px; + + .exit-button { + height: 10px; + width: 26px; + + position: absolute; + top: -10px; + right: 0; + } + + p { + @include title-center(); + + font-weight: bold; + margin-bottom: 5px; + } + + .items-overlay__rows-container { + display: flex; + flex-direction: column; + justify-content: space-evenly; + row-gap: 10px; + + .items-overlay__row { + display: flex; + justify-content: space-around; + align-items: center; + + padding: 10px; + text-transform: uppercase; + + background-color: gainsboro; + border: 1px solid gainsboro; + border-radius: 10px; + width: 95%; + margin: auto; + + .item-icon { + font-size: 2rem; + } + + .play-button { + height: 10px; + } + } + } + + .items-overlay__empty-container { + height: 80%; + + @include center-flex; + flex-direction: column; + + h3 { + text-transform: uppercase; + } + + i { + font-size: 3rem; + } + } +} diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.ts b/src/app/modules/plates/items-overlay/items-overlay.component.ts new file mode 100644 index 0000000..b629b0b --- /dev/null +++ b/src/app/modules/plates/items-overlay/items-overlay.component.ts @@ -0,0 +1,22 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {MenuItem} from "../../orders/order"; +import {I18nService} from "../../../services/i18n.service"; + +@Component({ + selector: 'items-overlay', + templateUrl: './items-overlay.component.html', + styleUrls: ['./items-overlay.component.scss'] +}) +export class ItemsOverlayComponent { + + public readonly i18n: any; + + @Input() public items: MenuItem[] = []; + + @Output() public onClose: EventEmitter = new EventEmitter(false); + @Output() public onRun: EventEmitter = new EventEmitter(false); + + constructor(public i18nService: I18nService) { + this.i18n = i18nService.instance; + } +} diff --git a/src/app/modules/plates/plate.interface.ts b/src/app/modules/plates/plate.interface.ts index b8cb822..097389c 100644 --- a/src/app/modules/plates/plate.interface.ts +++ b/src/app/modules/plates/plate.interface.ts @@ -19,6 +19,7 @@ export enum PlateItemStatus { export type PlateItemAction = PlateItemStatus | Status; export interface ItemEvent { + plateId: string; action: PlateItemAction; item: MenuItem; nextId?: string; diff --git a/src/app/modules/plates/plate/plate.component.html b/src/app/modules/plates/plate/plate.component.html index fa2e0b6..842093b 100644 --- a/src/app/modules/plates/plate/plate.component.html +++ b/src/app/modules/plates/plate/plate.component.html @@ -24,10 +24,19 @@

    {{i18n.PLATE.EMPTY}}

    - - + +
    + +
    @@ -65,3 +74,8 @@

    {{i18n.PLATE.FORM.TITLE}}

    + + + diff --git a/src/app/modules/plates/plate/plate.component.scss b/src/app/modules/plates/plate/plate.component.scss index f849893..fecc917 100644 --- a/src/app/modules/plates/plate/plate.component.scss +++ b/src/app/modules/plates/plate/plate.component.scss @@ -5,6 +5,7 @@ section { height: 100%; margin: 10px; + position: relative; header { position: fixed; @@ -64,6 +65,23 @@ section { text-transform: uppercase; } + + p-badge { + position: absolute; + right: -10px; + bottom: -10px; + + &:hover { + cursor: pointer; + } + } + + items-overlay { + position: absolute; + bottom: 30px; + left: 0; + right: 0; + } } .off { diff --git a/src/app/modules/plates/plate/plate.component.ts b/src/app/modules/plates/plate/plate.component.ts index 031e364..9645840 100644 --- a/src/app/modules/plates/plate/plate.component.ts +++ b/src/app/modules/plates/plate/plate.component.ts @@ -1,19 +1,20 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {mode, PlateInterface} from "../plate.interface"; +import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import {ItemEvent, mode, PlateInterface} from "../plate.interface"; import {I18nService} from "../../../services/i18n.service"; import {Plate} from "./plate.model"; import {FormControl, FormGroup, Validators} from "@angular/forms"; import {Routing} from "../../../app-routing.module"; import {ActivatedRoute} from "@angular/router"; import {ReactiveQueue} from "../../shared/class/reactive-queue"; -import {MenuItem} from "../../orders/order"; +import {MenuItem, Status} from "../../orders/order"; +import {Subscription} from "rxjs"; @Component({ selector: 'plate', templateUrl: './plate.component.html', styleUrls: ['./plate.component.scss'] }) -export class PlateComponent implements OnInit { +export class PlateComponent implements OnInit, OnDestroy { public readonly i18n: any; @@ -21,11 +22,18 @@ export class PlateComponent implements OnInit { public plateMode: typeof PlateInterface = mode(); public form?: FormGroup | undefined; public showExpand: boolean = true; + public badgeSize: string = "large"; + public badgeColor: string = "info"; + public showOverlay: boolean = false; + public progressItems: MenuItem[] = []; + public todoItems: MenuItem[] = []; + @Output() public onItemEvent: EventEmitter = new EventEmitter(false); @Input() public config!: Plate; @Input() public queue!: ReactiveQueue; @Output() public onNew: EventEmitter = new EventEmitter(true); + private queue$: Subscription = new Subscription(); constructor(public i18nService: I18nService, private _route: ActivatedRoute) { @@ -38,6 +46,25 @@ export class PlateComponent implements OnInit { this.showExpand = !params["id"]; } ); + + this.queue$.add(this.queue.values$.subscribe((items: MenuItem[] = []) => { + this.progressItems = []; + this.todoItems = []; + for (const i of items) { + if (i.status === Status.Progress) + this.progressItems.push(i); + else + this.todoItems.push(i); + } + if (this.todoItems.length == 0) { + this.showOverlay = false; + } + }) + ); + } + + public ngOnDestroy(): void { + this.queue$.unsubscribe(); } public onMouseEnter(): void { @@ -66,11 +93,43 @@ export class PlateComponent implements OnInit { this.config.mode = PlateInterface.Form; } - public discardForm() { + public discardForm(): void { this.config.mode = PlateInterface.Skeleton; } - public expandTab() { + public expandTab(): void { app.openNewTab(Routing.Plates, this.config._id!); } + + public onBadgeMouseEnter(): void { + this.badgeSize = "xlarge"; + this.badgeColor = "danger"; + } + + public onBadgeMouseLeave(): void { + if (!this.showOverlay) { + this.badgeSize = "large"; + this.badgeColor = "info"; + } + } + + public onBadgeMouseClick(): void { + this.showOverlay = !this.showOverlay; + if (this.showOverlay) + this.onBadgeMouseEnter(); + else + this.onBadgeMouseLeave(); + } + + public onItemStart(id: string) { + const event: ItemEvent = { + action: Status.Progress, + item: { + _id: id + }, + plateId: this.config._id! + } + + this.onItemEvent.emit(event); + } } diff --git a/src/app/modules/plates/plates.module.ts b/src/app/modules/plates/plates.module.ts index 6bb1e29..7647c3a 100644 --- a/src/app/modules/plates/plates.module.ts +++ b/src/app/modules/plates/plates.module.ts @@ -12,6 +12,9 @@ import {ReactiveFormsModule} from "@angular/forms"; import {InputNumberModule} from "primeng/inputnumber"; import {PlatePageComponent} from "./page/plate-page.component"; import {ItemComponent} from './item/item.component'; +import {BadgeModule} from "primeng/badge"; +import {ItemsOverlayComponent} from './items-overlay/items-overlay.component'; +import {TooltipModule} from 'primeng/tooltip'; const routes: Routes = [ { @@ -29,7 +32,8 @@ const routes: Routes = [ PlatesComponent, PlateComponent, PlatePageComponent, - ItemComponent + ItemComponent, + ItemsOverlayComponent ], exports: [ PlateComponent @@ -43,7 +47,9 @@ const routes: Routes = [ ButtonModule, RippleModule, ReactiveFormsModule, - InputNumberModule + InputNumberModule, + BadgeModule, + TooltipModule ] }) export class PlatesModule { diff --git a/src/app/modules/plates/plates/plates.component.html b/src/app/modules/plates/plates/plates.component.html index 13d940e..2d9e4d4 100644 --- a/src/app/modules/plates/plates/plates.component.html +++ b/src/app/modules/plates/plates/plates.component.html @@ -11,6 +11,7 @@

    {{i18n.PLATE.TITLE}}

    diff --git a/src/app/modules/plates/plates/plates.component.ts b/src/app/modules/plates/plates/plates.component.ts index 169721c..0089cd5 100644 --- a/src/app/modules/plates/plates/plates.component.ts +++ b/src/app/modules/plates/plates/plates.component.ts @@ -1,5 +1,5 @@ import {AfterViewInit, Component, ElementRef, Inject, OnInit} from '@angular/core'; -import {mode, PlateInterface} from "../plate.interface"; +import {ItemEvent, mode, PlateInterface} from "../plate.interface"; import {I18nService} from "../../../services/i18n.service"; import {Plate} from "../plate/plate.model"; import {ApiConnector} from "../../../services/api-connector"; @@ -120,4 +120,8 @@ export class PlatesComponent implements OnInit, AfterViewInit { this.totalPages = Math.ceil(this._total / this.DISPLAY_CHUNK); }); } + + public handleItemEvent(event: ItemEvent): void { + this.plateQueueManagerService.onItemAction(event.plateId, event.item, event.action); + } } diff --git a/src/app/modules/plates/services/plate-queue-manager.service.ts b/src/app/modules/plates/services/plate-queue-manager.service.ts index 7a1419d..ca275a2 100644 --- a/src/app/modules/plates/services/plate-queue-manager.service.ts +++ b/src/app/modules/plates/services/plate-queue-manager.service.ts @@ -38,6 +38,7 @@ export class PlateQueueManagerService { public sendToQueue(id: string, item: MenuItem): void { this._validateItem(item); + item.status = Status.Todo; this._getQueue(id).enqueue(item); this._changes$.next(this._changes$.value + 1); } @@ -67,14 +68,23 @@ export class PlateQueueManagerService { this.removeFromQueue(id, item); //TODO: Invoke order service break; + case Status.Progress: + this._runItemProgress(id, item); + break; default: console.warn("[QueueManager] Action not found"); break; } } + private _runItemProgress(plateId: string, item: MenuItem): void { + const queue: ReactiveQueue = this._getQueue(plateId); + queue.values.find(i => item._id === i._id)!.status = Status.Progress; + queue.refresh(); + } + private _validateItem(item: MenuItem): void { - if (!item || !item._id || !item.name) { + if (!item || !item._id) { throw new Error("Selected item is invalid!"); } } diff --git a/src/app/modules/shared/class/reactive-queue.ts b/src/app/modules/shared/class/reactive-queue.ts index 481803c..ea98ca1 100644 --- a/src/app/modules/shared/class/reactive-queue.ts +++ b/src/app/modules/shared/class/reactive-queue.ts @@ -1,10 +1,12 @@ -import {Observable, of} from "rxjs"; +import {BehaviorSubject, Observable, of} from "rxjs"; export class ReactiveQueue { private readonly items: T[]; + private readonly items$: BehaviorSubject; constructor(items?: T[]) { this.items = items ?? []; + this.items$ = new BehaviorSubject(this.items); } get dequeue(): T | undefined { @@ -25,7 +27,7 @@ export class ReactiveQueue { } get values$(): Observable { - return of(this.items); + return this.items$ } get isEmpty$(): Observable { @@ -35,4 +37,8 @@ export class ReactiveQueue { public enqueue(value: T): void { this.values.push(value); } + + public refresh() { + this.items$.next(this.items); + } } diff --git a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts index 25bc5ff..2108e13 100644 --- a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts +++ b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts @@ -3,9 +3,12 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; @Component({ selector: 'navbar-button', template: ` - `, styleUrls: ['navbar-button.component.scss'] @@ -16,10 +19,7 @@ export class NavbarButtonComponent { @Input() public active: boolean = false; @Input() public badged?: boolean = false; @Input() public badgeCounter?: number | null; + @Input() public title!: string; - @Output() onClick: EventEmitter = new EventEmitter(true); - - public click() { - this.onClick.emit(true); - } + @Output() public onClick: EventEmitter = new EventEmitter(true); } diff --git a/src/app/modules/shared/components/navbar/navbar.component.html b/src/app/modules/shared/components/navbar/navbar.component.html index 1198499..7df89fb 100644 --- a/src/app/modules/shared/components/navbar/navbar.component.html +++ b/src/app/modules/shared/components/navbar/navbar.component.html @@ -1,20 +1,24 @@
    diff --git a/src/app/modules/shared/components/navbar/navbar.component.ts b/src/app/modules/shared/components/navbar/navbar.component.ts index 0e379f0..f0a8238 100644 --- a/src/app/modules/shared/components/navbar/navbar.component.ts +++ b/src/app/modules/shared/components/navbar/navbar.component.ts @@ -2,6 +2,7 @@ import {Component} from '@angular/core'; import {Router} from "@angular/router"; import {Routing} from "../../../../app-routing.module"; import {PlateQueueManagerService} from "../../../plates/services/plate-queue-manager.service"; +import {I18nService} from "../../../../services/i18n.service"; @Component({ selector: 'navbar', @@ -10,10 +11,14 @@ import {PlateQueueManagerService} from "../../../plates/services/plate-queue-man }) export class NavbarComponent { + public readonly i18n: any; + public selectedRoute?: Routing = undefined; constructor(public plateQueueManagerService: PlateQueueManagerService, + public i18nService: I18nService, private _router: Router) { + this.i18n = i18nService.instance; } public get routing(): typeof Routing { diff --git a/src/app/modules/shared/shared.module.ts b/src/app/modules/shared/shared.module.ts index 190735f..f984d48 100644 --- a/src/app/modules/shared/shared.module.ts +++ b/src/app/modules/shared/shared.module.ts @@ -9,6 +9,7 @@ import {ButtonModule} from "primeng/button"; import {RippleModule} from "primeng/ripple"; import {TagModule} from "primeng/tag"; import {BadgeModule} from "primeng/badge"; +import {TooltipModule} from 'primeng/tooltip'; @NgModule({ declarations: [ @@ -23,7 +24,8 @@ import {BadgeModule} from "primeng/badge"; ButtonModule, RippleModule, TagModule, - BadgeModule + BadgeModule, + TooltipModule ], exports: [ NavbarButtonComponent, diff --git a/src/assets/i18n-ita.ts b/src/assets/i18n-ita.ts index fad1593..661072e 100644 --- a/src/assets/i18n-ita.ts +++ b/src/assets/i18n-ita.ts @@ -11,6 +11,9 @@ export const I18N = { NAME: "Nome Piastra", COLOR: "Colore", NUMBER: "Numero posti" + }, + OVERLAY: { + EMPTY: "Nessun ordine in attesa" } }, SETTINGS: { @@ -23,5 +26,8 @@ export const I18N = { }, ORDERS: { TITLE: "Gestione Ordini" + }, + DASHBOARD: { + TITLE: "Home" } } From 21cf8057b58844da4d65ce3868592ab843364564 Mon Sep 17 00:00:00 2001 From: bozzelliandrea Date: Sun, 24 Jul 2022 00:10:14 +0200 Subject: [PATCH 2/3] [Plate] Event Implementation * Implemented queue logic for item progress actions * Created new deleted actions dropdown --- .../modules/plates/item/item.component.html | 28 +++++++- .../modules/plates/item/item.component.scss | 38 ++++++++++ src/app/modules/plates/item/item.component.ts | 72 +++++++++++++++++-- src/app/modules/plates/plate.interface.ts | 1 - .../modules/plates/plate/plate.component.html | 7 +- .../modules/plates/plate/plate.component.ts | 18 +++-- .../plates/plates/plates.component.html | 1 + .../modules/plates/plates/plates.component.ts | 2 +- .../services/plate-queue-manager.service.ts | 16 +++-- 9 files changed, 161 insertions(+), 22 deletions(-) diff --git a/src/app/modules/plates/item/item.component.html b/src/app/modules/plates/item/item.component.html index fd1dafc..9a66179 100644 --- a/src/app/modules/plates/item/item.component.html +++ b/src/app/modules/plates/item/item.component.html @@ -12,7 +12,31 @@
- - + + + + +
+ + + + + + + + + + + +
+
diff --git a/src/app/modules/plates/item/item.component.scss b/src/app/modules/plates/item/item.component.scss index 1738077..ec3b312 100644 --- a/src/app/modules/plates/item/item.component.scss +++ b/src/app/modules/plates/item/item.component.scss @@ -81,3 +81,41 @@ justify-content: space-evenly; } } + +.delete-options__container { + position: absolute; + top: 0; + right: 0; + z-index: 1; + + background-color: white; + width: 50%; + + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: baseline; + + border: 1px solid black; + border-radius: 5px; + + span { + width: 100%; + padding: 5px; + + label { + margin-left: 10px; + + &:hover { + cursor: pointer; + } + } + + &:hover { + cursor: pointer; + background-color: gainsboro; + border: 1px solid black; + border-radius: 5px; + } + } +} diff --git a/src/app/modules/plates/item/item.component.ts b/src/app/modules/plates/item/item.component.ts index dfed982..f20b59c 100644 --- a/src/app/modules/plates/item/item.component.ts +++ b/src/app/modules/plates/item/item.component.ts @@ -1,19 +1,59 @@ -import {Component, EventEmitter, Input, Output} from '@angular/core'; -import {ItemEvent} from "../plate.interface"; +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {ItemEvent, PlateInterface, PlateItemAction, PlateItemStatus} from "../plate.interface"; import {MenuItem, Status} from "../../orders/order"; +import {MenuItem as PrimeMenuItem} from 'primeng/api'; +import {Plate} from "../plate/plate.model"; @Component({ selector: 'item', templateUrl: './item.component.html', styleUrls: ['./item.component.scss'] }) -export class ItemComponent { +export class ItemComponent implements OnInit { @Input() public config!: MenuItem; + @Input() public plateList: Plate[] = []; @Output() public onDoneEvent: EventEmitter = new EventEmitter(false); @Output() public onCancelEvent: EventEmitter = new EventEmitter(false); + public deleteOptions: PrimeMenuItem[] = []; + public deleteOverlay: boolean = false; + public showPlateList: boolean = false; + + public ngOnInit(): void { + this.deleteOptions = [ + { + icon: 'pi pi-trash', + label: 'Elimina', + command: () => { + this.onCancel(Status.Cancelled); + } + }, + { + icon: 'pi pi-undo', + label: 'Rimetti in Attesa', + command: () => { + this.onCancel(Status.Todo); + } + }, + { + icon: 'pi pi-directions', + label: 'Sposta in altra Piastra', + command: () => { + this.showPlateList = true; + } + }, + { + icon: 'pi pi-chevron-up', + label: 'Annulla', + command: () => { + this.toggleOverlay(); + } + }, + ]; + } + public onDone(): void { this.onDoneEvent.emit({ action: Status.Done, @@ -21,15 +61,33 @@ export class ItemComponent { } as ItemEvent); } - public onCancel(): void { + public onCancel(status: PlateItemAction): void { const event: ItemEvent = { - action: Status.Cancelled, + action: status, item: this.config } as ItemEvent; - //TODO: Handle moved or re-queued reasons - this.onCancelEvent.emit(event); + this.toggleOverlay(); } + public toggleOverlay(): void { + this.deleteOverlay = !this.deleteOverlay; + this.showPlateList = false; + } + + public getPlateList(): Plate[] { + return this.plateList.filter(p => p.mode === PlateInterface.On); + } + + public onPlateMoved(plate: Plate): void { + const event: ItemEvent = { + action: PlateItemStatus.Moved, + item: this.config, + nextId: plate._id + } as ItemEvent; + + this.onCancelEvent.emit(event); + this.toggleOverlay(); + } } diff --git a/src/app/modules/plates/plate.interface.ts b/src/app/modules/plates/plate.interface.ts index 097389c..6bb0f56 100644 --- a/src/app/modules/plates/plate.interface.ts +++ b/src/app/modules/plates/plate.interface.ts @@ -13,7 +13,6 @@ export function mode(): typeof PlateInterface { export enum PlateItemStatus { Moved = "MOVED", - ReQueued = "RE_QUEUED" } export type PlateItemAction = PlateItemStatus | Status; diff --git a/src/app/modules/plates/plate/plate.component.html b/src/app/modules/plates/plate/plate.component.html index 842093b..2090c04 100644 --- a/src/app/modules/plates/plate/plate.component.html +++ b/src/app/modules/plates/plate/plate.component.html @@ -19,13 +19,16 @@

{{config.name}}

[value]="config._status!" styleClass="mr-2"> - +

{{i18n.PLATE.EMPTY}}

- +
diff --git a/src/app/modules/plates/plate/plate.component.ts b/src/app/modules/plates/plate/plate.component.ts index 9645840..123ef07 100644 --- a/src/app/modules/plates/plate/plate.component.ts +++ b/src/app/modules/plates/plate/plate.component.ts @@ -16,6 +16,13 @@ import {Subscription} from "rxjs"; }) export class PlateComponent implements OnInit, OnDestroy { + @Input() public config!: Plate; + @Input() public plateList: Plate[] = []; + @Input() public queue!: ReactiveQueue; + + @Output() public onNew: EventEmitter = new EventEmitter(true); + @Output() public onItemEvent: EventEmitter = new EventEmitter(false); + public readonly i18n: any; public icon: string = "pi-plus"; @@ -27,12 +34,7 @@ export class PlateComponent implements OnInit, OnDestroy { public showOverlay: boolean = false; public progressItems: MenuItem[] = []; public todoItems: MenuItem[] = []; - @Output() public onItemEvent: EventEmitter = new EventEmitter(false); - @Input() public config!: Plate; - @Input() public queue!: ReactiveQueue; - - @Output() public onNew: EventEmitter = new EventEmitter(true); private queue$: Subscription = new Subscription(); constructor(public i18nService: I18nService, @@ -121,6 +123,12 @@ export class PlateComponent implements OnInit, OnDestroy { this.onBadgeMouseLeave(); } + public handleItemEvent(event: ItemEvent) { + event.plateId = this.config._id!; + + this.onItemEvent.emit(event); + } + public onItemStart(id: string) { const event: ItemEvent = { action: Status.Progress, diff --git a/src/app/modules/plates/plates/plates.component.html b/src/app/modules/plates/plates/plates.component.html index 2d9e4d4..ac02cdb 100644 --- a/src/app/modules/plates/plates/plates.component.html +++ b/src/app/modules/plates/plates/plates.component.html @@ -13,6 +13,7 @@

{{i18n.PLATE.TITLE}}

diff --git a/src/app/modules/plates/plates/plates.component.ts b/src/app/modules/plates/plates/plates.component.ts index 0089cd5..11a9491 100644 --- a/src/app/modules/plates/plates/plates.component.ts +++ b/src/app/modules/plates/plates/plates.component.ts @@ -122,6 +122,6 @@ export class PlatesComponent implements OnInit, AfterViewInit { } public handleItemEvent(event: ItemEvent): void { - this.plateQueueManagerService.onItemAction(event.plateId, event.item, event.action); + this.plateQueueManagerService.onItemAction(event.plateId, event.item, event.action, event.nextId); } } diff --git a/src/app/modules/plates/services/plate-queue-manager.service.ts b/src/app/modules/plates/services/plate-queue-manager.service.ts index ca275a2..8336da7 100644 --- a/src/app/modules/plates/services/plate-queue-manager.service.ts +++ b/src/app/modules/plates/services/plate-queue-manager.service.ts @@ -41,6 +41,7 @@ export class PlateQueueManagerService { item.status = Status.Todo; this._getQueue(id).enqueue(item); this._changes$.next(this._changes$.value + 1); + this._getQueue(id).refresh(); } public removeFromQueue(id: string, item: MenuItem): void { @@ -59,12 +60,13 @@ export class PlateQueueManagerService { case PlateItemStatus.Moved: if (!nextId) throw new Error("No queue selected to move the item"); this.sendToQueue(nextId, item); - this.onItemAction(nextId, item, Status.Cancelled); + this.onItemAction(id, item, Status.Cancelled); break; - case PlateItemStatus.ReQueued: - this.sendToQueue(id, item); + case Status.Todo: + this._resetItem(id, item); break; - case Status.Cancelled || Status.Done: + case Status.Cancelled: + case Status.Done: this.removeFromQueue(id, item); //TODO: Invoke order service break; @@ -77,6 +79,12 @@ export class PlateQueueManagerService { } } + private _resetItem(plateId: string, item: MenuItem) { + const queue: ReactiveQueue = this._getQueue(plateId); + queue.values.find(i => item._id === i._id)!.status = Status.Todo; + queue.refresh(); + } + private _runItemProgress(plateId: string, item: MenuItem): void { const queue: ReactiveQueue = this._getQueue(plateId); queue.values.find(i => item._id === i._id)!.status = Status.Progress; From 1051c12b3ce45cabd2b540f3d4c41dc7befd75bb Mon Sep 17 00:00:00 2001 From: bozzelliandrea Date: Sun, 24 Jul 2022 13:21:05 +0200 Subject: [PATCH 3/3] [Plate] Event Implementation * Replaced menu item logic with Order class * Added new unassigned button dropdown for new order without one selected plate --- .../orders/order-new/order-new.component.ts | 7 +- src/app/modules/orders/order.ts | 3 +- .../modules/plates/item/item.component.html | 6 +- src/app/modules/plates/item/item.component.ts | 10 +- .../items-overlay.component.html | 10 +- .../items-overlay.component.scss | 2 +- .../items-overlay/items-overlay.component.ts | 7 +- src/app/modules/plates/plate.interface.ts | 4 +- .../modules/plates/plate/plate.component.html | 4 +- .../modules/plates/plate/plate.component.ts | 36 +++-- .../plates/plates/plates.component.html | 28 +++- .../plates/plates/plates.component.scss | 129 ++++++++++++++++++ .../modules/plates/plates/plates.component.ts | 51 +++++-- .../services/plate-queue-manager.service.ts | 41 +++--- .../navbar-button/navbar-button.component.ts | 7 +- 15 files changed, 271 insertions(+), 74 deletions(-) diff --git a/src/app/modules/orders/order-new/order-new.component.ts b/src/app/modules/orders/order-new/order-new.component.ts index 7b6dc60..d814eaa 100644 --- a/src/app/modules/orders/order-new/order-new.component.ts +++ b/src/app/modules/orders/order-new/order-new.component.ts @@ -151,8 +151,11 @@ export class OrderNewComponent implements OnInit, OnDestroy { } }); this.apiConnector.addOrders(this.orders).subscribe(() => { - this.orders.filter(order => !!order.plate).forEach(order => { - this._plateQueueManagerService.sendToQueue(order.plate?._id!, order.menuItem); + this.orders.forEach(order => { + if (order.plate) + this._plateQueueManagerService.sendToQueue(order.plate?._id!, order); + else + this._plateQueueManagerService.sendToQueue(PlateQueueManagerService.UNASSIGNED_QUEUE, order); }); this.router.navigate(['/orders']); }); diff --git a/src/app/modules/orders/order.ts b/src/app/modules/orders/order.ts index 1498b23..d3a73e3 100644 --- a/src/app/modules/orders/order.ts +++ b/src/app/modules/orders/order.ts @@ -6,7 +6,7 @@ export interface Order { orderId: number, menuItem: MenuItem, plate?: Plate | null, - status: Status, + status: PlateItemAction, date: string | null, notes?: string } @@ -16,7 +16,6 @@ export interface MenuItem { name?: string, description?: string category?: Category - status?: PlateItemAction; } export interface MenuItemExtended extends MenuItem { diff --git a/src/app/modules/plates/item/item.component.html b/src/app/modules/plates/item/item.component.html index 9a66179..e8cb204 100644 --- a/src/app/modules/plates/item/item.component.html +++ b/src/app/modules/plates/item/item.component.html @@ -3,8 +3,8 @@
- {{config.name}} - ordine 10 + {{config.menuItem.name}} + ORDINE {{config.orderId}}
  • + ketchup
  • @@ -34,7 +34,7 @@ - + diff --git a/src/app/modules/plates/item/item.component.ts b/src/app/modules/plates/item/item.component.ts index f20b59c..6b99d80 100644 --- a/src/app/modules/plates/item/item.component.ts +++ b/src/app/modules/plates/item/item.component.ts @@ -1,6 +1,6 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {ItemEvent, PlateInterface, PlateItemAction, PlateItemStatus} from "../plate.interface"; -import {MenuItem, Status} from "../../orders/order"; +import {ItemEvent, PlateItemAction, PlateItemStatus} from "../plate.interface"; +import {Order, Status} from "../../orders/order"; import {MenuItem as PrimeMenuItem} from 'primeng/api'; import {Plate} from "../plate/plate.model"; @@ -11,7 +11,7 @@ import {Plate} from "../plate/plate.model"; }) export class ItemComponent implements OnInit { - @Input() public config!: MenuItem; + @Input() public config!: Order; @Input() public plateList: Plate[] = []; @Output() public onDoneEvent: EventEmitter = new EventEmitter(false); @@ -76,10 +76,6 @@ export class ItemComponent implements OnInit { this.showPlateList = false; } - public getPlateList(): Plate[] { - return this.plateList.filter(p => p.mode === PlateInterface.On); - } - public onPlateMoved(plate: Plate): void { const event: ItemEvent = { action: PlateItemStatus.Moved, diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.html b/src/app/modules/plates/items-overlay/items-overlay.component.html index 380cb80..471bb4f 100644 --- a/src/app/modules/plates/items-overlay/items-overlay.component.html +++ b/src/app/modules/plates/items-overlay/items-overlay.component.html @@ -1,20 +1,22 @@
    -

    Ordini in Attesa

    +

    Ordini in Attesa

    - {{i.name}} - ORDINE -
    diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.scss b/src/app/modules/plates/items-overlay/items-overlay.component.scss index 81999f8..563ad2a 100644 --- a/src/app/modules/plates/items-overlay/items-overlay.component.scss +++ b/src/app/modules/plates/items-overlay/items-overlay.component.scss @@ -60,7 +60,7 @@ section { } .items-overlay__empty-container { - height: 80%; + height: 100%; @include center-flex; flex-direction: column; diff --git a/src/app/modules/plates/items-overlay/items-overlay.component.ts b/src/app/modules/plates/items-overlay/items-overlay.component.ts index b629b0b..d34575a 100644 --- a/src/app/modules/plates/items-overlay/items-overlay.component.ts +++ b/src/app/modules/plates/items-overlay/items-overlay.component.ts @@ -1,5 +1,5 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; -import {MenuItem} from "../../orders/order"; +import {Order} from "../../orders/order"; import {I18nService} from "../../../services/i18n.service"; @Component({ @@ -11,10 +11,11 @@ export class ItemsOverlayComponent { public readonly i18n: any; - @Input() public items: MenuItem[] = []; + @Input() public items: Order[] = []; + @Input() public hideCloseButton: boolean = false; @Output() public onClose: EventEmitter = new EventEmitter(false); - @Output() public onRun: EventEmitter = new EventEmitter(false); + @Output() public onRun: EventEmitter = new EventEmitter(false); constructor(public i18nService: I18nService) { this.i18n = i18nService.instance; diff --git a/src/app/modules/plates/plate.interface.ts b/src/app/modules/plates/plate.interface.ts index 6bb0f56..f297c72 100644 --- a/src/app/modules/plates/plate.interface.ts +++ b/src/app/modules/plates/plate.interface.ts @@ -1,4 +1,4 @@ -import {MenuItem, Status} from "../orders/order"; +import {Order, Status} from "../orders/order"; export enum PlateInterface { Skeleton = "skeleton", @@ -20,6 +20,6 @@ export type PlateItemAction = PlateItemStatus | Status; export interface ItemEvent { plateId: string; action: PlateItemAction; - item: MenuItem; + item: Order; nextId?: string; } diff --git a/src/app/modules/plates/plate/plate.component.html b/src/app/modules/plates/plate/plate.component.html index 2090c04..9e45925 100644 --- a/src/app/modules/plates/plate/plate.component.html +++ b/src/app/modules/plates/plate/plate.component.html @@ -12,6 +12,9 @@

    {{config.name}}

    @@ -35,7 +38,6 @@

    {{i18n.PLATE.EMPTY}}

    ; + @Input() public queue!: ReactiveQueue; @Output() public onNew: EventEmitter = new EventEmitter(true); @Output() public onItemEvent: EventEmitter = new EventEmitter(false); @@ -32,8 +32,8 @@ export class PlateComponent implements OnInit, OnDestroy { public badgeSize: string = "large"; public badgeColor: string = "info"; public showOverlay: boolean = false; - public progressItems: MenuItem[] = []; - public todoItems: MenuItem[] = []; + public progressItems: Order[] = []; + public todoItems: Order[] = []; private queue$: Subscription = new Subscription(); @@ -49,17 +49,17 @@ export class PlateComponent implements OnInit, OnDestroy { } ); - this.queue$.add(this.queue.values$.subscribe((items: MenuItem[] = []) => { - this.progressItems = []; - this.todoItems = []; - for (const i of items) { - if (i.status === Status.Progress) - this.progressItems.push(i); - else - this.todoItems.push(i); - } - if (this.todoItems.length == 0) { - this.showOverlay = false; + this.queue$.add(this.queue.values$.subscribe((items: Order[] = []) => { + this.progressItems = []; + this.todoItems = []; + for (const i of items) { + if (i.status === Status.Progress) + this.progressItems.push(i); + else + this.todoItems.push(i); + } + if (this.todoItems.length == 0) { + this.showOverlay = false; } }) ); @@ -129,12 +129,10 @@ export class PlateComponent implements OnInit, OnDestroy { this.onItemEvent.emit(event); } - public onItemStart(id: string) { + public onItemStart(item: Order) { const event: ItemEvent = { action: Status.Progress, - item: { - _id: id - }, + item: item, plateId: this.config._id! } diff --git a/src/app/modules/plates/plates/plates.component.html b/src/app/modules/plates/plates/plates.component.html index ac02cdb..ebef777 100644 --- a/src/app/modules/plates/plates/plates.component.html +++ b/src/app/modules/plates/plates/plates.component.html @@ -1,4 +1,13 @@ -

    {{i18n.PLATE.TITLE}}

    +

    + {{i18n.PLATE.TITLE}} + + + +

    - + + + + + +
    + + + +
    +
    diff --git a/src/app/modules/plates/plates/plates.component.scss b/src/app/modules/plates/plates/plates.component.scss index a29ec25..b43529f 100644 --- a/src/app/modules/plates/plates/plates.component.scss +++ b/src/app/modules/plates/plates/plates.component.scss @@ -2,6 +2,97 @@ h3 { @include title-center; + + position: relative; + + button { + position: absolute; + right: 10%; + z-index: 1000; + + width: 200px; + height: 45px; + + font-size: 14px; + background-color: transparent; + transition: background-color 500ms linear; + + padding: 10px; + border: 3px solid var(--primary-500); + border-radius: 10px; + + span { + cursor: pointer; + display: inline-block; + position: relative; + transition: 0.5s; + + &:after { + content: '\00bb'; + position: absolute; + transform: rotate(90deg); + opacity: 0; + top: 0; + right: -20px; + transition: 0.5s; + } + } + + p-badge { + position: absolute; + top: -10px; + right: -10px; + } + + &:hover { + cursor: pointer; + + span { + padding-right: 25px; + + &:after { + opacity: 1; + right: 0; + } + } + } + } + + .button__active-overlay { + + background-color: var(--primary-100); + transition: background-color 500ms linear; + + span { + padding-right: 25px; + + &:after { + content: '\00bb'; + transform: rotate(-90deg); + opacity: 1; + top: 0; + right: 0; + } + } + } + + items-overlay { + height: 210px; + width: 40%; + margin: 0; + + position: absolute; + right: 10%; + top: 56px; + z-index: 1000; + + font-weight: 100; + font-size: 16px; + + ::ng-deep section { + border: 1px solid black; + } + } } .plates-carousel { @@ -62,3 +153,41 @@ h3 { right: 0; } } + +.plates-options__container { + position: absolute; + top: 56px; + left: 90%; + right: 1%; + z-index: 1000; + + background-color: white; + border: 1px solid black; + border-radius: 5px; + font-weight: 100; + + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: baseline; + + span { + width: 100%; + padding: 5px; + + label { + margin-left: 10px; + + &:hover { + cursor: pointer; + } + } + + &:hover { + cursor: pointer; + background-color: gainsboro; + border: 1px solid black; + border-radius: 5px; + } + } +} diff --git a/src/app/modules/plates/plates/plates.component.ts b/src/app/modules/plates/plates/plates.component.ts index 11a9491..3ebe668 100644 --- a/src/app/modules/plates/plates/plates.component.ts +++ b/src/app/modules/plates/plates/plates.component.ts @@ -1,16 +1,18 @@ -import {AfterViewInit, Component, ElementRef, Inject, OnInit} from '@angular/core'; -import {ItemEvent, mode, PlateInterface} from "../plate.interface"; +import {AfterViewInit, Component, ElementRef, Inject, OnDestroy, OnInit} from '@angular/core'; +import {ItemEvent, mode, PlateInterface, PlateItemStatus} from "../plate.interface"; import {I18nService} from "../../../services/i18n.service"; import {Plate} from "../plate/plate.model"; import {ApiConnector} from "../../../services/api-connector"; import {PlateQueueManagerService} from "../services/plate-queue-manager.service"; +import {Subscription} from "rxjs"; +import {Order} from "../../orders/order"; @Component({ selector: 'plates', templateUrl: './plates.component.html', styleUrls: ['./plates.component.scss'] }) -export class PlatesComponent implements OnInit, AfterViewInit { +export class PlatesComponent implements OnInit, AfterViewInit, OnDestroy { public readonly i18n: any; public readonly DISPLAY_CHUNK = 3; @@ -21,13 +23,17 @@ export class PlatesComponent implements OnInit, AfterViewInit { public plateList!: Plate[]; public currentPage: number = 0; public totalPages: number = 0; + public showOverlay: boolean = false; + public showPlateList: boolean = false; + public unassignedItems: Order[] = []; private readonly _MIN_DELTA_SWIPE = 90; private _start: number = 0; private _end: number = 0; private _total: number = 0; - + private _queue$: Subscription = new Subscription(); + private _currentItem?: Order; constructor(public i18nService: I18nService, public plateQueueManagerService: PlateQueueManagerService, @@ -38,6 +44,12 @@ export class PlatesComponent implements OnInit, AfterViewInit { public ngOnInit(): void { this._loadPlatesConfig(); + this._queue$.add( + this.plateQueueManagerService.getQueue(PlateQueueManagerService.UNASSIGNED_QUEUE) + .values$?.subscribe((items: Order[]) => { + this.unassignedItems = items; + }) + ); } public ngAfterViewInit(): void { @@ -62,6 +74,10 @@ export class PlatesComponent implements OnInit, AfterViewInit { .addEventListener('mouseup', () => this._swipeEnd()); } + public ngOnDestroy(): void { + this._queue$.unsubscribe(); + } + public onNextPage(): void { if ((this.currentPage + 1) === this.totalPages) { return @@ -85,6 +101,29 @@ export class PlatesComponent implements OnInit, AfterViewInit { this._apiConnector.addPlate(config).subscribe(() => this._loadPlatesConfig()); } + public handleItemEvent(event: ItemEvent): void { + this.plateQueueManagerService.onItemAction(event.plateId, event.item, event.action, event.nextId); + } + + public onUnassignedRun(item: Order): void { + this.showPlateList = true; + this._currentItem = item; + } + + public onUnassignedExecuteRun(plate: Plate): void { + this.plateQueueManagerService.onItemAction(PlateQueueManagerService.UNASSIGNED_QUEUE, this._currentItem!, PlateItemStatus.Moved, plate._id); + this.showPlateList = false; + } + + public toggleNoQueuedItemsOverlay() { + this.showOverlay = !this.showOverlay; + this.showPlateList = false; + } + + public getEnabledPlateList(skip: Plate | null): Plate[] { + return this.plateList.filter(p => p.mode === PlateInterface.On && p._id !== skip?._id); + } + private _swipeStart(event: Touch) { this._start = event.screenX; } @@ -120,8 +159,4 @@ export class PlatesComponent implements OnInit, AfterViewInit { this.totalPages = Math.ceil(this._total / this.DISPLAY_CHUNK); }); } - - public handleItemEvent(event: ItemEvent): void { - this.plateQueueManagerService.onItemAction(event.plateId, event.item, event.action, event.nextId); - } } diff --git a/src/app/modules/plates/services/plate-queue-manager.service.ts b/src/app/modules/plates/services/plate-queue-manager.service.ts index 8336da7..75ea1b4 100644 --- a/src/app/modules/plates/services/plate-queue-manager.service.ts +++ b/src/app/modules/plates/services/plate-queue-manager.service.ts @@ -1,16 +1,18 @@ import {Injectable} from '@angular/core'; import {ReactiveQueue} from "../../shared/class/reactive-queue"; import {Plate} from "../plate/plate.model"; -import {MenuItem, Status} from "../../orders/order"; import {PlateItemAction, PlateItemStatus} from "../plate.interface"; import {BehaviorSubject} from "rxjs"; +import {Order, Status} from "../../orders/order"; @Injectable({ providedIn: 'root' }) export class PlateQueueManagerService { - private _plates: Map> = new Map>(); + public static readonly UNASSIGNED_QUEUE: string = "UNASSIGNED_QUEUE"; + + private _plates: Map> = new Map>(); private _changes$: BehaviorSubject = new BehaviorSubject(0); constructor() { @@ -18,9 +20,10 @@ export class PlateQueueManagerService { public load(plates: Plate[]) { for (const plate of plates) this.addQueue(plate); + this._plates.set(PlateQueueManagerService.UNASSIGNED_QUEUE, new ReactiveQueue()); } - public getQueue(id: string): ReactiveQueue { + public getQueue(id: string): ReactiveQueue { return this._plates.get(id)!; } @@ -36,7 +39,7 @@ export class PlateQueueManagerService { return this._changes$.value > 0; } - public sendToQueue(id: string, item: MenuItem): void { + public sendToQueue(id: string, item: Order): void { this._validateItem(item); item.status = Status.Todo; this._getQueue(id).enqueue(item); @@ -44,16 +47,17 @@ export class PlateQueueManagerService { this._getQueue(id).refresh(); } - public removeFromQueue(id: string, item: MenuItem): void { + public removeFromQueue(id: string, item: Order): void { this._validateItem(item); - const queue: ReactiveQueue = this._getQueue(id); - queue.values = queue.values.filter((i: MenuItem) => { + const queue: ReactiveQueue = this._getQueue(id); + queue.values = queue.values.filter((i: Order) => { return i._id != item._id; }); this._changes$.next(this._changes$.value - 1); + queue.refresh(); } - public onItemAction(id: string, item: MenuItem, action: PlateItemAction, nextId?: string): void { + public onItemAction(id: string, item: Order, action: PlateItemAction, nextId?: string): void { this._validateItem(item); switch (action) { @@ -79,30 +83,35 @@ export class PlateQueueManagerService { } } - private _resetItem(plateId: string, item: MenuItem) { - const queue: ReactiveQueue = this._getQueue(plateId); - queue.values.find(i => item._id === i._id)!.status = Status.Todo; + private _resetItem(plateId: string, item: Order) { + const queue: ReactiveQueue = this._getQueue(plateId); + const foundItem: Order | undefined = queue.values.find(i => item._id === i._id); + if (foundItem) { + foundItem.status = Status.Todo + } else { + queue.enqueue(item); + } queue.refresh(); } - private _runItemProgress(plateId: string, item: MenuItem): void { - const queue: ReactiveQueue = this._getQueue(plateId); + private _runItemProgress(plateId: string, item: Order): void { + const queue: ReactiveQueue = this._getQueue(plateId); queue.values.find(i => item._id === i._id)!.status = Status.Progress; queue.refresh(); } - private _validateItem(item: MenuItem): void { + private _validateItem(item: Order): void { if (!item || !item._id) { throw new Error("Selected item is invalid!"); } } - private _getQueue(id: string): ReactiveQueue { + private _getQueue(id: string): ReactiveQueue { if (!id) { throw new Error("Plate Id is undefined!"); } - const queue: ReactiveQueue = this.getQueue(id); + const queue: ReactiveQueue = this.getQueue(id); if (!queue) { throw new Error("No queue found!"); diff --git a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts index 2108e13..3c3ccaa 100644 --- a/src/app/modules/shared/components/navbar-button/navbar-button.component.ts +++ b/src/app/modules/shared/components/navbar-button/navbar-button.component.ts @@ -3,9 +3,10 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; @Component({ selector: 'navbar-button', template: ` -