add mixing topping with override
This commit is contained in:
parent
35ebde967d
commit
79dddd1fbc
15 changed files with 296 additions and 91 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import Lang from './shared/helpers/lang';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
|
@ -11,5 +12,7 @@ export class AppComponent implements OnInit {
|
|||
|
||||
ngOnInit(): void {
|
||||
this.titleService.setTitle('Recipe Manager | Tao Bin');
|
||||
// lang
|
||||
Lang.initLanguageSwitcher();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ export type RecipeOverview = {
|
|||
name: string;
|
||||
otherName: string;
|
||||
description: string;
|
||||
otherDescription: string;
|
||||
lastUpdated: Date;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<label class="label">Price</label>
|
||||
<input class="input input-sm input-bordered input-ghost w-full text-center" type="text" name="price" value="{{recipePrice()}}">
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasSubmenu()">
|
||||
<div *ngFor="let sub of listSubMenuProductcodes()">
|
||||
<button
|
||||
|
|
@ -153,17 +158,12 @@
|
|||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#name"
|
||||
class="btn btn-xs"
|
||||
>1</a
|
||||
>About</a
|
||||
>
|
||||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#recipeList"
|
||||
class="btn btn-xs"
|
||||
>2</a
|
||||
>
|
||||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#toppingSet"
|
||||
class="btn btn-xs"
|
||||
>3</a
|
||||
>Recipe List</a
|
||||
>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -279,14 +279,6 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
// console.log('Recipe List Form Changed', repl);
|
||||
this.repl = repl[1] as never[];
|
||||
this.tpl = repl[0] as never[];
|
||||
|
||||
// check length of toppinglist
|
||||
console.log(
|
||||
'tpl length',
|
||||
this.tpl.length,
|
||||
'original length',
|
||||
(this.rawRecipe! as any).ToppingSet.length
|
||||
);
|
||||
for (let ti = 0; ti < this.tpl.length; ti++) {
|
||||
// check at the same index
|
||||
if (!isEqual(this.tpl[ti][0], (this.rawRecipe as any).ToppingSet[ti])) {
|
||||
|
|
@ -352,4 +344,11 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
recipePrice = () =>
|
||||
this.rawRecipe != undefined &&
|
||||
this.rawRecipe != null &&
|
||||
Object.keys(this.rawRecipe as any).includes('cashPrice')
|
||||
? (this.rawRecipe as any).cashPrice
|
||||
: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="collapse collapse-open" *ngIf="isTopping(getTypeForRecipeListAtIndex(i)['id'])">
|
||||
<div class="collapse-title">Topping Settings</div>
|
||||
<!-- <div class="collapse-title">Topping Settings</div> -->
|
||||
<div class="collapse-content">
|
||||
<app-recipe-topping
|
||||
[productCode]="productCode"
|
||||
|
|
|
|||
|
|
@ -509,12 +509,19 @@ export class RecipeListComponent implements OnInit {
|
|||
}, 100);
|
||||
}
|
||||
|
||||
openRecipeListEditor(i: number) {
|
||||
async openRecipeListEditor(i: number) {
|
||||
|
||||
if(this.timeoutHandler){
|
||||
await Promise.resolve();
|
||||
if (this.timeoutHandler) {
|
||||
console.log("timeout get", this.timeout);
|
||||
if(this.timeout >= 20){
|
||||
if (this.timeout >= 20) {
|
||||
// alert("Opening Recipe List Editor in detail")
|
||||
if (confirm("Are you sure you want to open Recipe List Editor in detail?")) {
|
||||
this.showDetailRecipeList = true;
|
||||
} else {
|
||||
this.showDetailRecipeList = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clearInterval(this.timeoutHandler);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
<div [formGroup]="toppingForm">
|
||||
<div formArrayName="toppingList" *ngFor="let topping of toppingList.controls; let i = index">
|
||||
<div formGroupName="{{ i }}">
|
||||
<div
|
||||
formArrayName="toppingList"
|
||||
*ngFor="let topping of toppingList.controls; let i = index"
|
||||
>
|
||||
<!-- toppingList.at(i) -->
|
||||
<div class="space-y-2" formGroupName="{{ i }}">
|
||||
<!-- iterate through ListGroupId -->
|
||||
|
||||
<input type="checkbox" formControlName="isUse"/>
|
||||
<div class="flex space-x-2">
|
||||
<h3>Enable</h3>
|
||||
<input class="toggle" type="checkbox" formControlName="isUse" />
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-2 items-center">
|
||||
<!-- toppingGroup -->
|
||||
<ng-select
|
||||
class="w-52"
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
[compareWith]="this.compareFunc"
|
||||
|
|
@ -20,19 +31,71 @@
|
|||
</ng-select>
|
||||
<!-- defaultSelect -->
|
||||
<ng-select
|
||||
class="w-52"
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
[compareWith]="this.compareFunc"
|
||||
formControlName="defaultIDSelect"
|
||||
>
|
||||
<ng-option
|
||||
*ngFor="let item of getMembersByGroupId(getGroupIdByIndex(this.index!))"
|
||||
*ngFor="
|
||||
let item of getMembersByGroupId(getGroupIdByIndex(this.index!))
|
||||
"
|
||||
[value]="item.id.toString()"
|
||||
>
|
||||
<div>{{ item.name }} ({{ item.id }})</div>
|
||||
</ng-option>
|
||||
</ng-select>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center">
|
||||
<p class="text-sm">Mix with</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row space-x-2 items-center justify-center">
|
||||
<ng-select
|
||||
class="w-80"
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
(compareWith)="(this.compareFunc)"
|
||||
[multiple]="true"
|
||||
[maxSelectedItems]="3"
|
||||
(close)="registerExtraTopping(extraTopping)"
|
||||
[(ngModel)]="extraTopping"
|
||||
>
|
||||
<ng-option
|
||||
*ngFor="let item of allToppingsDefinitions"
|
||||
[value]="item.groupId.toString()"
|
||||
>
|
||||
<div>
|
||||
<p>{{ item.name }} ({{ item.groupId }}) </p>
|
||||
</div>
|
||||
</ng-option>
|
||||
</ng-select>
|
||||
|
||||
|
||||
</div>
|
||||
<div *ngFor="let item of extraTopping; let i = index">
|
||||
<div class="flex items-center space-y-2 space-x-2 justify-start">
|
||||
<p>{{getToppingDefinitionByGroupId(item)['name']}} ({{getToppingDefinitionByGroupId(item)['groupId']}})</p>
|
||||
<ng-select
|
||||
class="w-52"
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
[compareWith]="this.compareFunc"
|
||||
bindLabel="name"
|
||||
[(ngModel)]="this.extraToppingDefault[item]"
|
||||
(close)="triggerValueChange()"
|
||||
>
|
||||
<ng-option
|
||||
*ngFor="let item2 of getMembersByGroupId(item)"
|
||||
[value]="item2.id.toString()"
|
||||
>
|
||||
<div>{{ item2.name }} ({{ item2.id }})</div>
|
||||
</ng-option>
|
||||
</ng-select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export class RecipeToppingComponent implements OnInit {
|
|||
|
||||
allToppingsDefinitions:
|
||||
| { groupId: string; name: string; members: string; default: string }[]
|
||||
| null = [{ groupId: '0', name: 'none', members: '0', default: '0' }];
|
||||
| null = [{ groupId: '0', name: 'disabled', members: '0', default: '0' }];
|
||||
|
||||
allToppingMembersByGroup: {
|
||||
id: string;
|
||||
|
|
@ -39,8 +39,14 @@ export class RecipeToppingComponent implements OnInit {
|
|||
}[] = [];
|
||||
department = this._route.snapshot.paramMap.get('department');
|
||||
|
||||
// list group id
|
||||
listGroupId: any[] = [];
|
||||
|
||||
private _toppingSetOriginalArray!: ToppingSet[];
|
||||
|
||||
extraTopping: [] = [];
|
||||
extraToppingDefault: {[key: string]: string} = {};
|
||||
|
||||
// form
|
||||
toppingForm = this._formBuilder.group(
|
||||
{
|
||||
|
|
@ -76,6 +82,8 @@ export class RecipeToppingComponent implements OnInit {
|
|||
this._toppingSetOriginalArray = data;
|
||||
console.log('ToppingSet', data, this.index, data.length >= this.index!, data[0]);
|
||||
|
||||
this.listGroupId.push(data[this.index!].ListGroupID);
|
||||
|
||||
// check length of toppingList if in range with given index
|
||||
if (data.length >= this.index!) {
|
||||
this.toppingList.push(
|
||||
|
|
@ -88,7 +96,7 @@ export class RecipeToppingComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
console.log('ToppingSet', this.toppingList);
|
||||
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
|
||||
});
|
||||
|
||||
// get all topping
|
||||
|
|
@ -120,27 +128,7 @@ export class RecipeToppingComponent implements OnInit {
|
|||
});
|
||||
|
||||
// emit value changes
|
||||
this.toppingForm.valueChanges.subscribe((value) => {
|
||||
console.log('emit value', value, 'for index: ', this.index! );
|
||||
|
||||
// transform data
|
||||
this.toppingList.value.forEach((value: any) => {
|
||||
value = this.transformToppingsetStructure(value);
|
||||
});
|
||||
|
||||
// extend lifetime of data
|
||||
let newMapping = this.toppingList.value.map((value: {
|
||||
isUse: boolean;
|
||||
groupID: string;
|
||||
defaultIDSelect: string;
|
||||
ListGroupID: string[];
|
||||
}) => this.transformToppingsetStructure(value));
|
||||
|
||||
// add debug here!
|
||||
console.log('newMapping', newMapping);
|
||||
|
||||
this.toppingSetChange.emit([this.index! , newMapping]);
|
||||
});
|
||||
this.toppingForm.valueChanges.subscribe((value) => {this.triggerValueChange();});
|
||||
}
|
||||
|
||||
compareFunc = (a: any, b: any) => a.toString() === b.toString();
|
||||
|
|
@ -175,6 +163,89 @@ export class RecipeToppingComponent implements OnInit {
|
|||
}
|
||||
});
|
||||
}
|
||||
getToppingDefinitionByGroupId(groupID: any) {
|
||||
|
||||
let result = (this.allToppingsDefinitions as any).find(
|
||||
(x: any) => x.groupId == groupID
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// for additional topping
|
||||
registerExtraTopping(event: any) {
|
||||
console.log("get value from extra topping", this.extraTopping, "default", this.extraToppingDefault, "param event", event);
|
||||
|
||||
this.extraTopping.forEach((x: any) => {
|
||||
// do check if x is registered
|
||||
if(this.extraToppingDefault[x] == null || this.extraToppingDefault[x] == undefined){
|
||||
this.bindDefaultToExtraTopping(x);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
syncWithExtraToppingDefault(groupId: string){
|
||||
console.log("syncWithExtraToppingDefault::GetId", groupId, "default", this.extraToppingDefault);
|
||||
|
||||
// sync to map
|
||||
|
||||
|
||||
}
|
||||
|
||||
clearExtraTopping($event: any){
|
||||
console.log("clear extra topping", $event);
|
||||
// get index value of removing element
|
||||
// let index = this.extraTopping.indexOf($event as never);
|
||||
let groupId = $event;
|
||||
// get index from extra default
|
||||
// let index = this.extraToppingDefault?.find((x: any) => x.groupId == $event);
|
||||
|
||||
// clear default from extra
|
||||
|
||||
|
||||
console.log("after clear", this.extraTopping, "default", this.extraToppingDefault);
|
||||
}
|
||||
|
||||
// getExtraDefault = (groupId: any) => (this.extraToppingDefault?.find((x: any) => x.groupId == groupId) as any)?.default;
|
||||
|
||||
triggerValueChange(){
|
||||
console.log('triggerValueChange');
|
||||
|
||||
// transform data
|
||||
this.toppingList.value.forEach((value: any) => {
|
||||
value = this.transformToppingsetStructure(value);
|
||||
});
|
||||
|
||||
// extend lifetime of data
|
||||
let newMapping = this.toppingList.value.map((value: {
|
||||
isUse: boolean;
|
||||
groupID: string;
|
||||
defaultIDSelect: string;
|
||||
ListGroupID: string[];
|
||||
}) => this.transformToppingsetStructure(value));
|
||||
|
||||
|
||||
|
||||
// before emit
|
||||
console.log("emit", newMapping);
|
||||
|
||||
// get current value of controls
|
||||
this.toppingSetChange.emit([this.index! , newMapping]);
|
||||
}
|
||||
|
||||
// bind default back to extraTopping
|
||||
bindDefaultToExtraTopping(groupId: any){
|
||||
this.extraToppingDefault![groupId] = '0';
|
||||
}
|
||||
|
||||
cloneValue(value: any){
|
||||
console.log('cloneValue', value);
|
||||
|
||||
// return a clone value that not address to the original value
|
||||
return JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
|
||||
transformToppingsetStructure = (value: any) => {
|
||||
|
||||
|
|
@ -192,6 +263,34 @@ export class RecipeToppingComponent implements OnInit {
|
|||
value.groupID = '0';
|
||||
}
|
||||
|
||||
// in case of.doing mix override topping
|
||||
if(this.extraTopping.length > 0){
|
||||
let concatArr = [value.ListGroupID[0], ...((this.extraTopping).map((x: string) => parseInt(x)))];
|
||||
|
||||
if(concatArr.length < 4){
|
||||
// fill with 0
|
||||
while (concatArr.length < 4) {
|
||||
concatArr.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("concatArr", concatArr);
|
||||
|
||||
value.ListGroupID = concatArr;
|
||||
|
||||
// get last element that is not 0
|
||||
let lastIndex = concatArr.findIndex((x: any) => x == 0) - 1;
|
||||
if(lastIndex <= -1){
|
||||
lastIndex = 0;
|
||||
}
|
||||
|
||||
value.defaultIDSelect = parseInt(this.extraToppingDefault![value.groupID]);
|
||||
// console.log("value.defaultIDSelect", value.defaultIDSelect);
|
||||
}
|
||||
|
||||
// do cat array from list group id
|
||||
// let testSpliceArr = Array(value.ListGroupID).splice(1, value.ListGroupID.length -1 , ...(this.listGroupId[0] as Array<string>).slice(1, value.ListGroupID.length));
|
||||
|
||||
return {
|
||||
isUse: value.isUse,
|
||||
groupID: value.groupID,
|
||||
|
|
|
|||
|
|
@ -346,6 +346,7 @@
|
|||
</td>
|
||||
<td class="px-6 py-4">{{ recipe.otherName }}</td>
|
||||
<td class="px-6 py-4 flex-wrap max-w-xs">{{ recipe.description }}</td>
|
||||
<td class="px-6 py-4 flex-wrap max-w-xs">{{ recipe.otherDescription }}</td>
|
||||
<td class="px-6 py-4">
|
||||
{{ recipe.lastUpdated | date : "dd-MMM-yyyy hh:mm:ss" }}
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
'Name',
|
||||
'Other Name',
|
||||
'Description',
|
||||
'Other Description',
|
||||
'Last Updated',
|
||||
];
|
||||
private offset = 0;
|
||||
|
|
@ -116,6 +117,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
materialIds: this.selectMaterialFilter || [],
|
||||
}))
|
||||
.subscribe(({ result, hasMore, totalCount }) => {
|
||||
// console.log("result in scroll", result);
|
||||
if (this.recipeOverviewList) {
|
||||
this.recipeOverviewList =
|
||||
this.recipeOverviewList.concat(result);
|
||||
|
|
@ -143,6 +145,10 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
|
||||
async ngOnInit(): Promise<void> {
|
||||
console.log('Trigger onInit where department = ', this.department);
|
||||
|
||||
|
||||
|
||||
|
||||
this.recipesDashboard$ = this._recipeService
|
||||
.getRecipesDashboard({
|
||||
filename: this._recipeService.getCurrentFile(),
|
||||
|
|
@ -224,9 +230,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||
},
|
||||
});
|
||||
|
||||
// TODO: get all materials; MaterialSetting + MaterialCode
|
||||
(await
|
||||
// TODO: get all materials; MaterialSetting + MaterialCode
|
||||
this._materialService
|
||||
.getMaterialCodes())
|
||||
.pipe(
|
||||
|
|
|
|||
25
client/src/app/shared/helpers/lang.ts
Normal file
25
client/src/app/shared/helpers/lang.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { AsyncStorage } from "./asyncStorage";
|
||||
|
||||
export default class Lang {
|
||||
|
||||
// init default language
|
||||
static async initLanguageSwitcher(){
|
||||
let currentLanguage = await Lang.getCurrentLanguage();
|
||||
if(currentLanguage == null || currentLanguage == undefined){
|
||||
await AsyncStorage.setItem('currentLanguage', 'th');
|
||||
}
|
||||
|
||||
console.log('initLanguageSwitcher::SetCurrentTo=>', await Lang.getCurrentLanguage());
|
||||
}
|
||||
|
||||
static getCurrentLanguage() {
|
||||
return AsyncStorage.getItem('currentLanguage');
|
||||
}
|
||||
|
||||
static async switchLanguage() {
|
||||
let currentLanguage = await Lang.getCurrentLanguage();
|
||||
let resultLang = currentLanguage == 'th' ? 'en' : 'th';
|
||||
// set back lang
|
||||
await AsyncStorage.setItem('currentLanguage', resultLang);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ type RecipeOverview struct {
|
|||
Name string `json:"name"`
|
||||
OtherName string `json:"otherName"`
|
||||
Description string `json:"description"`
|
||||
OtherDescription string `json:"otherDescription"`
|
||||
LastUpdated string `json:"lastUpdated"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
|
|||
d.taoLogger.Log.Error("GetRecipe01ByProductCode: Error when read recipe file, Return default recipe", zap.Error(err))
|
||||
for _, v := range d.currentRecipe[countryID].Recipe01 {
|
||||
if v.ProductCode == productCode {
|
||||
return v, nil
|
||||
return v, fmt.Errorf("[DEFAULT]-ERR")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ func (mr *MaterialRouter) GetFullMaterialDetail(w http.ResponseWriter, r *http.R
|
|||
materialDetails = append(materialDetails, map[string]interface{}{
|
||||
"materialId": matSetting.ID,
|
||||
"name": mat_name,
|
||||
"nameEN": matSetting.MaterialOtherName,
|
||||
"type": "powder:" + strconv.FormatBool(matSetting.PowderChannel) + ",syrup:" + strconv.FormatBool(matSetting.SyrupChannel) + ",bean:" + strconv.FormatBool(matSetting.BeanChannel) + ",equipment:" + strconv.FormatBool(matSetting.IsEquipment) + ",soda:" + strconv.FormatBool(matSetting.SodaChannel) + ",icecream:" + strconv.FormatBool(matSetting.IceScreamBingsuChannel),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ func (rs *recipeService) GetRecipeOverview(request *contracts.RecipeOverviewRequ
|
|||
Name: v.Name,
|
||||
OtherName: v.OtherName,
|
||||
Description: v.Description,
|
||||
OtherDescription: v.OtherDescription,
|
||||
LastUpdated: v.LastChange,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue