update recipe detail
This commit is contained in:
parent
d52cad09fd
commit
9279ef0247
11 changed files with 58 additions and 123 deletions
|
|
@ -29,12 +29,12 @@ export type RecipeDetail = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RecipeDetailMat = {
|
export type RecipeDetailMat = {
|
||||||
|
isUse: boolean;
|
||||||
materialID: number;
|
materialID: number;
|
||||||
name: string;
|
name: string;
|
||||||
mixOrder: number;
|
mixOrder: number;
|
||||||
feedParameter: number;
|
feedParameter: number;
|
||||||
feedPattern: number;
|
feedPattern: number;
|
||||||
isUse: boolean;
|
|
||||||
materialPathId: number;
|
materialPathId: number;
|
||||||
powderGram: number;
|
powderGram: number;
|
||||||
powderTime: number;
|
powderTime: number;
|
||||||
|
|
|
||||||
|
|
@ -87,36 +87,14 @@
|
||||||
formControlName="otherDescription"
|
formControlName="otherDescription"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<div class="form-control w-44">
|
|
||||||
<label class="flex gap-2 cursor-pointer label">
|
|
||||||
<span class="label-text">Is Use?</span>
|
|
||||||
<input type="checkbox" class="toggle" formControlName="isUse" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-control w-44">
|
|
||||||
<label class="flex gap-2 cursor-pointer label">
|
|
||||||
<span class="label-text">Is Show?</span>
|
|
||||||
<input type="checkbox" class="toggle" formControlName="isShow" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-control w-44">
|
|
||||||
<label class="flex gap-2 cursor-pointer label">
|
|
||||||
<span class="label-text">Is Disable?</span>
|
|
||||||
<input type="checkbox" class="toggle" formControlName="disable" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="col-span-3 overflow-auto mb-4 rounded bg-white border border-gray-200 shadow"
|
class="col-span-3 overflow-auto mb-4 rounded bg-white border border-gray-200 shadow"
|
||||||
>
|
>
|
||||||
<app-recipe-list
|
<app-recipe-list
|
||||||
[parentForm]="recipeDetailForm"
|
|
||||||
[productCode]="productCode"
|
[productCode]="productCode"
|
||||||
[actionRecord]="actionRecord"
|
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||||
[recipeDetailOriginal]="recipeOriginalDetail"
|
|
||||||
></app-recipe-list>
|
></app-recipe-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ export class RecipeDetailsComponent implements OnInit {
|
||||||
isUse: false,
|
isUse: false,
|
||||||
isShow: false,
|
isShow: false,
|
||||||
disable: false,
|
disable: false,
|
||||||
recipeListData: this._formBuilder.array([]),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|
@ -83,6 +82,8 @@ export class RecipeDetailsComponent implements OnInit {
|
||||||
this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() };
|
this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange);
|
||||||
|
|
||||||
// snap recipe detail form value
|
// snap recipe detail form value
|
||||||
|
|
||||||
this.actionRecord.registerOnAddAction((currAction, allAction) => {
|
this.actionRecord.registerOnAddAction((currAction, allAction) => {
|
||||||
|
|
@ -144,10 +145,14 @@ export class RecipeDetailsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get isValueChanged() {
|
isValueChanged: boolean = false;
|
||||||
return !isEqual(
|
|
||||||
this.recipeOriginalDetail,
|
onRecipeDetailFormChange(recipeDetail: typeof this.recipeDetailForm.value) {
|
||||||
this.recipeDetailForm.getRawValue()
|
console.log('Recipe Detail Form Changed', recipeDetail);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
onRecipeListFormChange(isValueChanged: boolean) {
|
||||||
|
console.log('Recipe List Form Changed', isValueChanged);
|
||||||
|
this.isValueChanged ||= isValueChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<table class="table" [formGroup]="parentForm">
|
<table class="table" [formGroup]="recipeListForm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-gray-200">
|
<tr class="bg-gray-200">
|
||||||
<th class="px-6 py-3">Action</th>
|
<th class="px-6 py-3">Is Use</th>
|
||||||
<th class="px-6 py-3">Material ID</th>
|
<th class="px-6 py-3">Material ID</th>
|
||||||
<th class="px-6 py-3">Material Name</th>
|
<th class="px-6 py-3">Material Name</th>
|
||||||
<th class="px-6 py-3">MixOrder</th>
|
<th class="px-6 py-3">MixOrder</th>
|
||||||
|
|
@ -20,17 +20,7 @@
|
||||||
>
|
>
|
||||||
<tr class="bg-white la border-b hover:bg-secondary" formGroupName="{{ i }}">
|
<tr class="bg-white la border-b hover:bg-secondary" formGroupName="{{ i }}">
|
||||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||||
<button
|
<input type="checkbox" class="toggle" formControlName="isUse" />
|
||||||
class="btn btn-primary"
|
|
||||||
(click)="deleteRecipeData(i)"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" (click)="addRecipeData()" type="button">
|
|
||||||
Add
|
|
||||||
</button>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||||
<input type="text" class="input" formControlName="materialID" />
|
<input type="text" class="input" formControlName="materialID" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { NgFor, NgIf } from '@angular/common';
|
import { NgFor, NgIf } from '@angular/common';
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
FormArray,
|
FormArray,
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
FormGroup,
|
FormGroup,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
|
import { isEqual, sortBy } from 'lodash';
|
||||||
import { first } from 'rxjs';
|
import { first } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
RecipeDetail,
|
RecipeDetail,
|
||||||
|
|
@ -15,20 +16,6 @@ import {
|
||||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||||
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
||||||
|
|
||||||
export interface RecipeListDataFormGroup {
|
|
||||||
id: FormControl<number | null>;
|
|
||||||
name: FormControl<string | null>;
|
|
||||||
enable: FormControl<boolean | null>;
|
|
||||||
mixOrder: FormControl<number | null>;
|
|
||||||
stirTime: FormControl<number | null>;
|
|
||||||
powderGram: FormControl<number | null>;
|
|
||||||
powderTime: FormControl<number | null>;
|
|
||||||
syrupGram: FormControl<number | null>;
|
|
||||||
syrupTime: FormControl<number | null>;
|
|
||||||
waterCold: FormControl<number | null>;
|
|
||||||
waterHot: FormControl<number | null>;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recipe-list',
|
selector: 'app-recipe-list',
|
||||||
templateUrl: './recipe-list.component.html',
|
templateUrl: './recipe-list.component.html',
|
||||||
|
|
@ -36,14 +23,8 @@ export interface RecipeListDataFormGroup {
|
||||||
imports: [NgIf, NgFor, ReactiveFormsModule],
|
imports: [NgIf, NgFor, ReactiveFormsModule],
|
||||||
})
|
})
|
||||||
export class RecipeListComponent implements OnInit {
|
export class RecipeListComponent implements OnInit {
|
||||||
@Input({ required: true }) parentForm!: FormGroup;
|
|
||||||
@Input({ required: true }) actionRecord!: ActionRecord<
|
|
||||||
RecipeDetail | RecipeDetailMat
|
|
||||||
>;
|
|
||||||
|
|
||||||
@Input({ required: true }) recipeDetailOriginal!: any;
|
|
||||||
|
|
||||||
@Input({ required: true }) productCode!: string;
|
@Input({ required: true }) productCode!: string;
|
||||||
|
@Output() recipeListFormChange = new EventEmitter<boolean>();
|
||||||
|
|
||||||
isMatLoaded: boolean = false;
|
isMatLoaded: boolean = false;
|
||||||
|
|
||||||
|
|
@ -52,20 +33,27 @@ export class RecipeListComponent implements OnInit {
|
||||||
private _formBuilder: FormBuilder
|
private _formBuilder: FormBuilder
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
recipeListForm = this._formBuilder.group(
|
||||||
|
{
|
||||||
|
recipeListData: this._formBuilder.array([]),
|
||||||
|
},
|
||||||
|
{ updateOn: 'blur' }
|
||||||
|
);
|
||||||
|
|
||||||
|
private _recipeListOriginalArray!: RecipeDetailMat[];
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this._recipeService
|
this._recipeService
|
||||||
.getRecipeDetailMat(this.productCode)
|
.getRecipeDetailMat(this.productCode)
|
||||||
.pipe(first())
|
.pipe(first())
|
||||||
.subscribe(({ result }) => {
|
.subscribe(({ result }) => {
|
||||||
if (this.recipeDetailOriginal)
|
this._recipeListOriginalArray = result;
|
||||||
this.recipeDetailOriginal.recipeListData = result;
|
|
||||||
else this.recipeDetailOriginal = { recipeListData: result };
|
|
||||||
result.forEach((recipeDetailMat: RecipeDetailMat) => {
|
result.forEach((recipeDetailMat: RecipeDetailMat) => {
|
||||||
this.recipeListData.push(
|
this.recipeListData.push(
|
||||||
this._formBuilder.group({
|
this._formBuilder.group({
|
||||||
|
isUse: recipeDetailMat.isUse,
|
||||||
materialID: recipeDetailMat.materialID,
|
materialID: recipeDetailMat.materialID,
|
||||||
name: recipeDetailMat.name,
|
name: [{ value: recipeDetailMat.name, disabled: true }],
|
||||||
enable: recipeDetailMat.isUse,
|
|
||||||
mixOrder: recipeDetailMat.mixOrder,
|
mixOrder: recipeDetailMat.mixOrder,
|
||||||
stirTime: recipeDetailMat.stirTime,
|
stirTime: recipeDetailMat.stirTime,
|
||||||
powderGram: recipeDetailMat.powderGram,
|
powderGram: recipeDetailMat.powderGram,
|
||||||
|
|
@ -79,43 +67,24 @@ export class RecipeListComponent implements OnInit {
|
||||||
});
|
});
|
||||||
this.isMatLoaded = true;
|
this.isMatLoaded = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.recipeListForm.valueChanges.subscribe((value) => {
|
||||||
|
console.log(value.recipeListData);
|
||||||
|
console.log(this._recipeListOriginalArray);
|
||||||
|
if (
|
||||||
|
!isEqual(
|
||||||
|
sortBy(value, 'materialID'),
|
||||||
|
sortBy(this._recipeListOriginalArray, 'materialID')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
this.recipeListFormChange.emit(true);
|
||||||
|
} else {
|
||||||
|
this.recipeListFormChange.emit(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get recipeListData(): FormArray {
|
get recipeListData(): FormArray {
|
||||||
return this.parentForm.get('recipeListData') as FormArray;
|
return this.recipeListForm.get('recipeListData') as FormArray;
|
||||||
}
|
|
||||||
|
|
||||||
addRecipeData(): void {
|
|
||||||
const newRecipeDetailMat: RecipeDetailMat = {
|
|
||||||
materialID: 0,
|
|
||||||
name: '',
|
|
||||||
mixOrder: 0,
|
|
||||||
feedParameter: 0,
|
|
||||||
feedPattern: 0,
|
|
||||||
isUse: false,
|
|
||||||
materialPathId: 0,
|
|
||||||
powderGram: 0,
|
|
||||||
powderTime: 0,
|
|
||||||
stirTime: 0,
|
|
||||||
syrupGram: 0,
|
|
||||||
syrupTime: 0,
|
|
||||||
waterCold: 0,
|
|
||||||
waterYield: 0,
|
|
||||||
};
|
|
||||||
this.recipeListData.push(this._formBuilder.group(newRecipeDetailMat));
|
|
||||||
this.actionRecord.addAction(
|
|
||||||
new Action('add', newRecipeDetailMat, 'recipeListData')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteRecipeData(index: number): void {
|
|
||||||
const recipeDetailMat: RecipeDetailMat =
|
|
||||||
this.recipeListData.at(index).value;
|
|
||||||
|
|
||||||
this.recipeListData.removeAt(index);
|
|
||||||
|
|
||||||
this.actionRecord.addAction(
|
|
||||||
new Action('delete', recipeDetailMat, 'recipeListData')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<main
|
<main
|
||||||
class="relative overflow-auto max-h-[900px] shadow-md sm:rounded-lg"
|
class="relative overflow-auto max-h-[80%] h-[88vh] shadow-md sm:rounded-lg"
|
||||||
#table
|
#table
|
||||||
>
|
>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|
|
||||||
|
|
@ -313,13 +313,15 @@ export class RecipesComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
openJsonTab() {
|
openJsonTab() {
|
||||||
window.open(
|
window.open(
|
||||||
environment.api + `/recipes/${this._recipeService.getCurrentFile()}/json`,
|
environment.api +
|
||||||
|
`/recipes/${this._recipeService.getCurrentCountry()}/${this._recipeService.getCurrentFile()}/json`,
|
||||||
'_blank'
|
'_blank'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToTop() {
|
scrollToTop() {
|
||||||
this.tableCtx!.nativeElement.scroll;
|
const table = this.tableCtx!.nativeElement;
|
||||||
|
table.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,12 @@ type RecipeDetailResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecipeDetailMat struct {
|
type RecipeDetailMat struct {
|
||||||
|
IsUse bool `json:"isUse"`
|
||||||
MaterialID uint64 `json:"materialID"`
|
MaterialID uint64 `json:"materialID"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
MixOrder int `json:"mixOrder"`
|
MixOrder int `json:"mixOrder"`
|
||||||
FeedParameter int `json:"feedParameter"`
|
FeedParameter int `json:"feedParameter"`
|
||||||
FeedPattern int `json:"feedPattern"`
|
FeedPattern int `json:"feedPattern"`
|
||||||
IsUse bool `json:"isUse"`
|
|
||||||
MaterialPathId int `json:"materialPathId"`
|
MaterialPathId int `json:"materialPathId"`
|
||||||
PowderGram int `json:"powderGram"`
|
PowderGram int `json:"powderGram"`
|
||||||
PowderTime int `json:"powderTime"`
|
PowderTime int `json:"powderTime"`
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ type Data struct {
|
||||||
func NewData() *Data {
|
func NewData() *Data {
|
||||||
|
|
||||||
countries := []helpers.CountryName{{
|
countries := []helpers.CountryName{{
|
||||||
CountryID: "thai",
|
CountryID: "tha",
|
||||||
CountryName: "Thailand",
|
CountryName: "Thailand",
|
||||||
}, {
|
}, {
|
||||||
CountryID: "mys",
|
CountryID: "mys",
|
||||||
|
|
@ -46,8 +46,8 @@ func NewData() *Data {
|
||||||
|
|
||||||
allRecipeFiles := helpers.ScanRecipeFiles(countries)
|
allRecipeFiles := helpers.ScanRecipeFiles(countries)
|
||||||
|
|
||||||
defaultFile := "coffeethai02_580.json"
|
defaultFile := "coffeethai02_600.json"
|
||||||
defaultCountry := "thai"
|
defaultCountry := "tha"
|
||||||
defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile)
|
defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,6 @@ func ReadFile(filePath string) (string, error) {
|
||||||
|
|
||||||
func ReadRecipeFile(countryID, filePath string) (*models.Recipe, error) {
|
func ReadRecipeFile(countryID, filePath string) (*models.Recipe, error) {
|
||||||
|
|
||||||
if countryID == "thai" {
|
|
||||||
countryID = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Open(path.Join("cofffeemachineConfig", countryID, filePath))
|
file, err := os.Open(path.Join("cofffeemachineConfig", countryID, filePath))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -69,12 +65,7 @@ func ScanRecipeFiles(countries []CountryName) map[string][]RecipePath {
|
||||||
recipeFiles := map[string][]RecipePath{}
|
recipeFiles := map[string][]RecipePath{}
|
||||||
|
|
||||||
for _, country := range countries {
|
for _, country := range countries {
|
||||||
var files []string
|
files := ListFile("cofffeemachineConfig/" + country.CountryID + "/coffeethai02_*.json")
|
||||||
if country.CountryID == "thai" {
|
|
||||||
files = ListFile("cofffeemachineConfig/coffeethai02_*.json")
|
|
||||||
} else {
|
|
||||||
files = ListFile("cofffeemachineConfig/" + country.CountryID + "/coffeethai02_*.json")
|
|
||||||
}
|
|
||||||
sort.Slice(files, func(i, j int) bool {
|
sort.Slice(files, func(i, j int) bool {
|
||||||
file1, err := os.Stat(files[i])
|
file1, err := os.Stat(files[i])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,12 @@ func (rs *recipeService) GetRecipeDetailMat(request *contracts.RecipeDetailReque
|
||||||
for _, mat := range matsCode {
|
for _, mat := range matsCode {
|
||||||
if v.MaterialPathId == int(mat.MaterialID) {
|
if v.MaterialPathId == int(mat.MaterialID) {
|
||||||
result.Result = append(result.Result, contracts.RecipeDetailMat{
|
result.Result = append(result.Result, contracts.RecipeDetailMat{
|
||||||
|
IsUse: v.IsUse,
|
||||||
MaterialID: mat.MaterialID,
|
MaterialID: mat.MaterialID,
|
||||||
Name: mat.PackageDescription,
|
Name: mat.PackageDescription,
|
||||||
MixOrder: v.MixOrder,
|
MixOrder: v.MixOrder,
|
||||||
FeedParameter: v.FeedParameter,
|
FeedParameter: v.FeedParameter,
|
||||||
FeedPattern: v.FeedPattern,
|
FeedPattern: v.FeedPattern,
|
||||||
IsUse: v.IsUse,
|
|
||||||
MaterialPathId: v.MaterialPathId,
|
MaterialPathId: v.MaterialPathId,
|
||||||
PowderGram: v.PowderGram,
|
PowderGram: v.PowderGram,
|
||||||
PowderTime: v.PowderTime,
|
PowderTime: v.PowderTime,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue