update recipe detail

This commit is contained in:
Kenta420 2023-11-27 19:58:07 +07:00
parent d52cad09fd
commit 9279ef0247
11 changed files with 58 additions and 123 deletions

View file

@ -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;

View file

@ -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">

View file

@ -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;
} }
} }

View file

@ -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" />

View file

@ -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')
);
} }
} }

View file

@ -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">

View file

@ -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 {

View file

@ -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"`

View file

@ -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 {

View file

@ -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])

View file

@ -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,