add filter with material
This commit is contained in:
parent
5b01f1c431
commit
70cfd89fc4
9 changed files with 135 additions and 14 deletions
18
client/package-lock.json
generated
18
client/package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
||||||
"@angular/platform-browser": "^16.2.0",
|
"@angular/platform-browser": "^16.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^16.2.0",
|
"@angular/platform-browser-dynamic": "^16.2.0",
|
||||||
"@angular/router": "^16.2.0",
|
"@angular/router": "^16.2.0",
|
||||||
|
"@ng-select/ng-select": "^11.2.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
|
|
@ -2925,6 +2926,23 @@
|
||||||
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@ng-select/ng-select": {
|
||||||
|
"version": "11.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-11.2.0.tgz",
|
||||||
|
"integrity": "sha512-lTyw93kFdKGecp9eKmOP0PQSCaAJS8DCt4D60ns055+ixvRSp2fuXAuJUvn1e3gAsvpZor37osmYlOJ4LYwYIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16",
|
||||||
|
"npm": ">= 8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^16.0.0",
|
||||||
|
"@angular/core": "^16.0.0",
|
||||||
|
"@angular/forms": "^16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ngtools/webpack": {
|
"node_modules/@ngtools/webpack": {
|
||||||
"version": "16.2.2",
|
"version": "16.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"@angular/platform-browser": "^16.2.0",
|
"@angular/platform-browser": "^16.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^16.2.0",
|
"@angular/platform-browser-dynamic": "^16.2.0",
|
||||||
"@angular/router": "^16.2.0",
|
"@angular/router": "^16.2.0",
|
||||||
|
"@ng-select/ng-select": "^11.2.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ const routes: Routes = [
|
||||||
path: 'recipes',
|
path: 'recipes',
|
||||||
loadComponent: () =>
|
loadComponent: () =>
|
||||||
import('./features/recipes/recipes.component').then(
|
import('./features/recipes/recipes.component').then(
|
||||||
(m) => m.DashboardComponent
|
(m) => m.RecipesComponent
|
||||||
),
|
),
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export class MaterialService {
|
||||||
`${environment.api}/materials/code`,
|
`${environment.api}/materials/code`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
country: country || '',
|
country: country || this.getCurrentCountry(),
|
||||||
filename: filename || '',
|
filename: filename || this.getCurrentFile(),
|
||||||
mat_ids: matIds?.join(',') || '',
|
mat_ids: matIds?.join(',') || '',
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
|
|
@ -35,11 +35,29 @@ export class MaterialService {
|
||||||
`${environment.api}/materials/setting/${id}`,
|
`${environment.api}/materials/setting/${id}`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
country: country || '',
|
country: country || this.getCurrentCountry(),
|
||||||
filename: filename || '',
|
filename: filename || this.getCurrentFile(),
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentFile(): string {
|
||||||
|
const currentRecipeFile = localStorage.getItem('currentRecipeFile');
|
||||||
|
if (currentRecipeFile) {
|
||||||
|
return currentRecipeFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'coffeethai02_580.json';
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentCountry(): string {
|
||||||
|
const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
|
||||||
|
if (currentRecipeCountry) {
|
||||||
|
return currentRecipeCountry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Thailand';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { RecipeMetaData } from 'src/app/shared/types/recipe';
|
||||||
interface RecipeParams {
|
interface RecipeParams {
|
||||||
filename: string;
|
filename: string;
|
||||||
country: string;
|
country: string;
|
||||||
|
materialIds: number[];
|
||||||
offset: number;
|
offset: number;
|
||||||
take: number;
|
take: number;
|
||||||
search: string;
|
search: string;
|
||||||
|
|
@ -31,6 +32,7 @@ export class RecipeService {
|
||||||
search: '',
|
search: '',
|
||||||
country: this.getCurrentCountry(),
|
country: this.getCurrentCountry(),
|
||||||
filename: this.getCurrentFile(),
|
filename: this.getCurrentFile(),
|
||||||
|
materialIds: [],
|
||||||
}
|
}
|
||||||
): Observable<{
|
): Observable<{
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
|
@ -48,6 +50,7 @@ export class RecipeService {
|
||||||
search: params.search,
|
search: params.search,
|
||||||
country: params.country,
|
country: params.country,
|
||||||
filename: params.filename,
|
filename: params.filename,
|
||||||
|
material_ids: params.materialIds.join(','),
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,25 @@
|
||||||
(input)="setSearch($event)"
|
(input)="setSearch($event)"
|
||||||
(keydown.enter)="search($event)"
|
(keydown.enter)="search($event)"
|
||||||
/>
|
/>
|
||||||
|
<ng-select
|
||||||
|
[items]="materialList"
|
||||||
|
class="join-item text-base"
|
||||||
|
bindLabel="name"
|
||||||
|
bindValue="id"
|
||||||
|
[multiple]="true"
|
||||||
|
[closeOnSelect]="false"
|
||||||
|
[(ngModel)]="selectMaterialFilter"
|
||||||
|
>
|
||||||
|
<ng-template ng-option-tmp let-item="item">
|
||||||
|
<p class="text-xs">{{ item.name }}</p>
|
||||||
|
<small class="text-xs text-gray-500">{{ item.id }}</small>
|
||||||
|
</ng-template>
|
||||||
|
</ng-select>
|
||||||
<button class="btn join-item" (click)="search($event)">
|
<button class="btn join-item" (click)="search($event)">
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button class="btn rounded-lg" (click)="openJsonTab()">
|
<button class="btn rounded-lg" (click)="openJsonTab()">
|
||||||
View JSON
|
View JSON
|
||||||
|
|
|
||||||
|
|
@ -5,27 +5,37 @@ import {
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { UserService } from 'src/app/core/services/user.service';
|
import { CommonModule, DatePipe } from '@angular/common';
|
||||||
import { User } from 'src/app/core/models/user.model';
|
|
||||||
import { DatePipe, NgFor, NgIf } from '@angular/common';
|
|
||||||
import { Recipe, Recipe01 } from 'src/app/core/models/recipe.model';
|
import { Recipe, Recipe01 } from 'src/app/core/models/recipe.model';
|
||||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { RecipeModalComponent } from 'src/app/shared/modal/recipe-details/recipe-modal.component';
|
import { RecipeModalComponent } from 'src/app/shared/modal/recipe-details/recipe-modal.component';
|
||||||
import { BehaviorSubject, Subject, Subscriber, Subscription } from 'rxjs';
|
import { BehaviorSubject, Subscription, map } from 'rxjs';
|
||||||
import * as lodash from 'lodash';
|
import * as lodash from 'lodash';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { MaterialService } from 'src/app/core/services/material.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recipes',
|
selector: 'app-recipes',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterLink, NgIf, NgFor, DatePipe, RecipeModalComponent],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterLink,
|
||||||
|
DatePipe,
|
||||||
|
RecipeModalComponent,
|
||||||
|
NgSelectModule,
|
||||||
|
FormsModule,
|
||||||
|
],
|
||||||
templateUrl: './recipes.component.html',
|
templateUrl: './recipes.component.html',
|
||||||
})
|
})
|
||||||
export class DashboardComponent implements OnInit, OnDestroy {
|
export class RecipesComponent implements OnInit, OnDestroy {
|
||||||
recipes: Recipe | null = null;
|
recipes: Recipe | null = null;
|
||||||
recipes01: Recipe01[] | null = null;
|
recipes01: Recipe01[] | null = null;
|
||||||
currentFile: string = '';
|
currentFile: string = '';
|
||||||
|
selectMaterialFilter: number[] | null = null;
|
||||||
|
materialList: { id: number; name: string | number }[] | null = null;
|
||||||
|
|
||||||
tableHeads: string[] = [
|
tableHeads: string[] = [
|
||||||
'Product Code',
|
'Product Code',
|
||||||
|
|
@ -68,6 +78,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
search: this.oldSearchStr,
|
search: this.oldSearchStr,
|
||||||
filename: this._recipeService.getCurrentFile(),
|
filename: this._recipeService.getCurrentFile(),
|
||||||
country: this._recipeService.getCurrentCountry(),
|
country: this._recipeService.getCurrentCountry(),
|
||||||
|
materialIds: this.selectMaterialFilter || [],
|
||||||
})
|
})
|
||||||
.subscribe(({ recipes, hasMore, fileName }) => {
|
.subscribe(({ recipes, hasMore, fileName }) => {
|
||||||
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
||||||
|
|
@ -91,7 +102,10 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private _recipeService: RecipeService) {}
|
constructor(
|
||||||
|
private _recipeService: RecipeService,
|
||||||
|
private _materialService: MaterialService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this._recipeService
|
this._recipeService
|
||||||
|
|
@ -101,6 +115,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
search: this.oldSearchStr,
|
search: this.oldSearchStr,
|
||||||
filename: this._recipeService.getCurrentFile(),
|
filename: this._recipeService.getCurrentFile(),
|
||||||
country: this._recipeService.getCurrentCountry(),
|
country: this._recipeService.getCurrentCountry(),
|
||||||
|
materialIds: this.selectMaterialFilter || [],
|
||||||
})
|
})
|
||||||
.subscribe(({ recipes, hasMore, fileName }) => {
|
.subscribe(({ recipes, hasMore, fileName }) => {
|
||||||
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
||||||
|
|
@ -119,6 +134,20 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
this.isHasMore = hasMore;
|
this.isHasMore = hasMore;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._materialService
|
||||||
|
.getMaterialCodes()
|
||||||
|
.pipe(
|
||||||
|
map((mat) =>
|
||||||
|
mat.map((m) => ({
|
||||||
|
id: m.materialID,
|
||||||
|
name: m.PackageDescription || m.materialID,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.subscribe((materials) => {
|
||||||
|
this.materialList = materials;
|
||||||
|
});
|
||||||
|
|
||||||
this.initRecipeSelection();
|
this.initRecipeSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +165,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
search: this.searchStr,
|
search: this.searchStr,
|
||||||
filename: this._recipeService.getCurrentFile(),
|
filename: this._recipeService.getCurrentFile(),
|
||||||
country: this._recipeService.getCurrentCountry(),
|
country: this._recipeService.getCurrentCountry(),
|
||||||
|
materialIds: this.selectMaterialFilter || [],
|
||||||
})
|
})
|
||||||
.subscribe(({ recipes, hasMore, fileName }) => {
|
.subscribe(({ recipes, hasMore, fileName }) => {
|
||||||
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
||||||
|
|
@ -268,6 +298,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
search: this.oldSearchStr,
|
search: this.oldSearchStr,
|
||||||
filename: recipeFileName,
|
filename: recipeFileName,
|
||||||
country: this.selectedCountry!,
|
country: this.selectedCountry!,
|
||||||
|
materialIds: this.selectMaterialFilter || [],
|
||||||
})
|
})
|
||||||
.subscribe(({ recipes, hasMore, fileName }) => {
|
.subscribe(({ recipes, hasMore, fileName }) => {
|
||||||
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,14 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@import url('https://fonts.googleapis.com/css?family=Kanit');
|
@import url('https://fonts.googleapis.com/css?family=Kanit');
|
||||||
|
@import "~@ng-select/ng-select/themes/default.theme.css";
|
||||||
|
|
||||||
|
.ng-select-container {
|
||||||
|
max-width: 400px;
|
||||||
|
font-family: 'Kanit', sans-serif;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ng-value-container {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,16 @@ func (rr *RecipeRouter) Route(r chi.Router) {
|
||||||
|
|
||||||
country := r.URL.Query().Get("country")
|
country := r.URL.Query().Get("country")
|
||||||
filename := r.URL.Query().Get("filename")
|
filename := r.URL.Query().Get("filename")
|
||||||
|
materialIds := r.URL.Query().Get("material_ids")
|
||||||
|
|
||||||
|
var materialIdsUint []uint64
|
||||||
|
for _, v := range strings.Split(materialIds, ",") {
|
||||||
|
materialIdUint, err := strconv.ParseUint(v, 10, 64)
|
||||||
|
if err != nil || materialIdUint == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
materialIdsUint = append(materialIdsUint, materialIdUint)
|
||||||
|
}
|
||||||
|
|
||||||
countryID, err := rr.data.GetCountryIDByName(country)
|
countryID, err := rr.data.GetCountryIDByName(country)
|
||||||
|
|
||||||
|
|
@ -72,6 +82,20 @@ func (rr *RecipeRouter) Route(r chi.Router) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(materialIdsUint) > 0 {
|
||||||
|
resultFilter := []models.Recipe01{}
|
||||||
|
for _, v := range recipe.Recipe01 {
|
||||||
|
for _, matID := range materialIdsUint {
|
||||||
|
for _, recipe := range v.Recipes {
|
||||||
|
if recipe.IsUse && uint64(recipe.MaterialPathId) == matID {
|
||||||
|
resultFilter = append(resultFilter, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recipe.Recipe01 = resultFilter
|
||||||
|
}
|
||||||
|
|
||||||
isHasMore := len(recipe.Recipe01) >= int(take+offset)
|
isHasMore := len(recipe.Recipe01) >= int(take+offset)
|
||||||
if isHasMore {
|
if isHasMore {
|
||||||
recipe.Recipe01 = recipe.Recipe01[offset : take+offset]
|
recipe.Recipe01 = recipe.Recipe01[offset : take+offset]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue