import { CommonModule, DatePipe } from '@angular/common'; import { Component, EventEmitter, OnInit } from '@angular/core'; import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Observable, first, map } from 'rxjs'; import { RecipeService } from 'src/app/core/services/recipe.service'; import { ConfirmModal } from 'src/app/shared/modal/confirm/confirm-modal.component'; import { animate, style, transition, trigger } from '@angular/animations'; import { RecipeListComponent } from './recipe-list/recipe-list.component'; import { Recipe01, RecipeDetail, RecipeDetailMat, Topping, ToppingSet, } from 'src/app/core/models/recipe.model'; import { ActionRecord } from 'src/app/shared/actionRecord/actionRecord'; import { UserService } from 'src/app/core/services/user.service'; import { UserPermissions } from 'src/app/core/auth/userPermissions'; import { ToppingService } from 'src/app/core/services/topping.service'; import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; import { isEqual } from 'lodash'; @Component({ selector: 'app-recipe-details', templateUrl: './recipe-details.component.html', standalone: true, animations: [ trigger('inOutAnimation', [ transition(':enter', [ style({ opacity: 0 }), animate('1s ease-out', style({ opacity: 1 })), ]), ]), ], imports: [ CommonModule, RouterLink, ReactiveFormsModule, ConfirmModal, DatePipe, RecipeListComponent, FormsModule, ], }) export class RecipeDetailsComponent implements OnInit { title: string = 'Recipe Detail'; recipeDetail$!: Observable; isLoaded: boolean = false; isMatLoaded: boolean = false; actionRecord: ActionRecord = new ActionRecord(); recipeOriginalDetail!: typeof this.recipeDetailForm.value; commit_msg: string = ''; // department: string = this._route.parent!.snapshot.params['department']; constructor( private _formBuilder: FormBuilder, private _route: ActivatedRoute, private _router: Router, private _recipeService: RecipeService, private _toppingService: ToppingService, private _userService: UserService ) {} productCode!: any; changedProductCode: string | undefined = undefined; recipeDetailForm = this._formBuilder.group({ productCode: '', name: '', otherName: '', description: '', otherDescription: '', lastModified: new Date(), price: 0, isUse: false, isShow: false, disable: false, }); repl = []; tpl = []; toppingSet: ToppingSet[] | null = null; submenus: Recipe01[] | null = null; rawRecipe: {} | undefined | null = undefined; async ngOnInit() { this.productCode = this._route.snapshot.params['productCode']; this.recipeDetail$ = ( await this._recipeService.getRecipeDetail(this.productCode) ).pipe(first()); this.recipeDetail$.subscribe((detail) => { // console.log('Recipe Detail', detail); this.recipeDetailForm.patchValue(detail); this.isLoaded = true; this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() }; }); this._recipeService .getSubMenus( await this._recipeService.getCurrentCountry(), this._recipeService.getCurrentFile(), this.productCode ) .subscribe((data) => { console.log('Submenus', data); this.submenus = data; }); this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange); ( await this._toppingService.getToppingsOfRecipe( this.department, this._recipeService.getCurrentFile(), this.productCode ) ).subscribe((data) => { this.toppingSet = data; // console.log('Toppings', data); }); // get full raw value of this recipe ( await this._recipeService.getRawRecipeOfProductCode( this.department, this._recipeService.getCurrentFile(), this.productCode ) ).subscribe((data) => { console.log('Raw Recipe', data); this.rawRecipe = data; }); // snap recipe detail form value this.actionRecord.registerOnAddAction((currAction, allAction) => { if (currAction.type === 'recipeListData') { switch (currAction.action) { case 'add': break; case 'delete': break; } } console.log('Action Record', allAction); }); } showConfirmSaveModal: EventEmitter = new EventEmitter(); showConfirmCloseModal: EventEmitter = new EventEmitter(); confirmSave = { title: 'The changes detected!', message: 'Do you want to save changes?', confirmCallBack: async () => { console.log('confirm save'); // get username let username: string = ''; username = this._userService.getCurrentUser()!.name; // diff with rawValue, then send let to_send = { edit_by: username, commit_msg: this.commit_msg, productCode: this.changedProductCode == undefined ? this.productCode : this.changedProductCode, name: this.recipeDetailForm.getRawValue().name != this.recipeOriginalDetail.name ? this.recipeDetailForm.getRawValue().name : this.recipeOriginalDetail.name, otherName: this.recipeDetailForm.getRawValue().otherName != this.recipeOriginalDetail.otherName ? this.recipeDetailForm.getRawValue().otherName : this.recipeOriginalDetail.otherName, description: this.recipeDetailForm.getRawValue().description != this.recipeOriginalDetail.description ? this.recipeDetailForm.getRawValue().description : this.recipeOriginalDetail.description, otherDescription: this.recipeDetailForm.getRawValue().otherDescription != this.recipeOriginalDetail.otherDescription ? this.recipeDetailForm.getRawValue().otherDescription : this.recipeOriginalDetail.otherDescription, LastChange: this.recipeDetailForm.getRawValue().lastModified != this.recipeOriginalDetail.lastModified ? this.recipeDetailForm.getRawValue().lastModified : this.recipeOriginalDetail.lastModified, price: this.recipeDetailForm.getRawValue().price != this.recipeOriginalDetail.price ? this.recipeDetailForm.getRawValue().price : this.recipeOriginalDetail.price, isUse: (this.rawRecipe as any).isUse, isShow: (this.rawRecipe as any).isShow, disable: (this.rawRecipe as any).disable, recipes: [...(this.repl.length <= 0 ? [] : this.repl)], SubMenu: [...((this.rawRecipe! as any).SubMenu!)], ToppingSet: [...((this.rawRecipe as any).ToppingSet)], }; // TODO: update value in targeted recipe console.log('to_send', to_send); this._recipeService.editChanges( await this._recipeService.getCurrentCountry(this.department), this._recipeService.getCurrentFile(), { ...to_send, } ); console.log('Sending changes'); void this._router.navigate(['/' + this.department + '/recipes']); }, }; onKeyUpCommitMsg(e: any) { this.commit_msg = e.target.value; } confirmClose = { title: 'The changes will be lost!', message: 'Do you want to close without saving?', confirmCallBack: () => { console.log('confirm close'); this._router.navigate(['/' + this.department + '/recipes']); }, }; onPressConfirmSave() { if (this.isValueChanged) { this.showConfirmSaveModal.emit(true); } else { this._router.navigate(['/' + this.department + '/recipes']); } } onPressConfirmClose() { if (this.isValueChanged) { this.showConfirmCloseModal.emit(true); } else { this._router.navigate(['/' + this.department + '/recipes']); } } isValueChanged: boolean = false; onRecipeDetailFormChange(recipeDetail: typeof this.recipeDetailForm.value) { // console.log('Recipe Detail Form Changed', recipeDetail); } onRecipeListFormChange(repl: unknown[]) { // 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])){ console.log('topping list changed', ti, this.tpl[ti][0], (this.rawRecipe as any).ToppingSet[ti]); // update raw recipe (this.rawRecipe as any).ToppingSet[ti] = this.tpl[ti][0]; console.log('after update topping', (this.rawRecipe as any).ToppingSet[ti]); } } // console.log('Recipe List Form Changed', this.repl, this.tpl); this.isValueChanged ||= repl != undefined; } onToppingListChange(tpl: unknown[]) { // console.log('Topping List Form Changed', tpl); this.tpl = tpl as never[]; this.isValueChanged ||= tpl != undefined; } isEditable() { return this._userService .getCurrentUser()! .permissions.includes(UserPermissions.EDITOR); } onProductCodeChange(event: any) { if (event.target.value != '') { this.changedProductCode = event.target.value; } } // Submenus selectedSubProductCode: string | undefined = undefined; hasSubmenu = () => this.submenus != null && this.submenus!.length > 0; listSubMenuProductcodes = () => this.submenus!.map((recipe) => recipe.productCode); selectSubmenu(productCode: string) { if (this.selectedSubProductCode == productCode) { this.selectedSubProductCode = undefined; console.log('Unselected submenu', productCode); return; } this.selectedSubProductCode = productCode; console.log('Selected submenu', productCode); } }