change save file method, add file changes history
This commit is contained in:
parent
519749fd3a
commit
820557a268
12 changed files with 2388 additions and 2036 deletions
|
|
@ -1,329 +1,332 @@
|
|||
<div class="p-4">
|
||||
<form class="grid grid-cols-3 gap-4 mb-4" [formGroup]="recipeDetailForm">
|
||||
<div
|
||||
class="block col-span-1 p-6 bg-white border border-gray-200 rounded-lg shadow"
|
||||
>
|
||||
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
|
||||
<div class="flex flex-wrap">
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ recipeDetailForm.getRawValue().name }}
|
||||
</h5>
|
||||
<h5 class="mb-2 px-3 text-xl font-bold text-gray-900">|</h5>
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ recipeDetailForm.getRawValue().otherName }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<div class="flex items-center">
|
||||
<p class="text-sm text-gray-500">Last Modify</p>
|
||||
<p class="ml-2 text-sm text-gray-900">
|
||||
{{
|
||||
recipeDetailForm.getRawValue().lastModified
|
||||
| date : "dd/MM/yyyy HH:mm:ss"
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex p-3 items-center justify-center w-full">
|
||||
<img
|
||||
class="rounded-lg shadow"
|
||||
src="/assets/{{ 'bn_hot_america_no' }}.png"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="block col-span-2 p-6 bg-white border border-gray-200 rounded-lg shadow min-h-[300px]"
|
||||
>
|
||||
<div
|
||||
*ngIf="isLoaded; else indicator"
|
||||
[@inOutAnimation]
|
||||
class="grid-cols-2 w-full flex flex-col gap-2"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<label class="label text-base mr-3 w-max"
|
||||
><span class="label-text text-base mr-3 w-max">Name:</span></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="name"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label">
|
||||
<span class="label-text text-base mr-3 w-max"
|
||||
>Other Name:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="otherName"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label"
|
||||
><span class="lable-text text-base mr-3 w-max"
|
||||
>Description:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="description"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label"
|
||||
><span class="label-text text-base mr-3 w-max"
|
||||
>Other Description:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="otherDescription"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-3 overflow-auto mb-4 rounded bg-white border border-gray-200 shadow"
|
||||
>
|
||||
<app-recipe-list
|
||||
[productCode]="productCode"
|
||||
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||
></app-recipe-list>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="sticky bottom-0 col-span-3 flex justify-end bg-white rounded-full drop-shadow-2xl p-3"
|
||||
>
|
||||
<button
|
||||
(click)="onPressConfirmClose()"
|
||||
class="btn btn-error w-36 text-white mr-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
(click)="onPressConfirmSave()"
|
||||
class="btn btn-success w-36 text-white"
|
||||
[disabled]="!isValueChanged"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<ng-template #indicator>
|
||||
<div class="flex w-full h-full justify-center items-center">
|
||||
<span class="loading loading-spinner w-20"></span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<confirm-modal
|
||||
[title]="confirmSave.title"
|
||||
[message]="confirmSave.message"
|
||||
[confirmCallBack]="confirmSave.confirmCallBack"
|
||||
[show]="showConfirmSaveModal"
|
||||
></confirm-modal>
|
||||
|
||||
<confirm-modal
|
||||
[title]="confirmClose.title"
|
||||
[message]="confirmClose.message"
|
||||
[confirmCallBack]="confirmClose.confirmCallBack"
|
||||
[show]="showConfirmCloseModal"
|
||||
></confirm-modal>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<form class="grid grid-cols-3 gap-4 mb-4" [formGroup]="recipeDetailForm">
|
||||
<div
|
||||
class="block col-span-1 p-6 bg-white border border-gray-200 rounded-lg shadow"
|
||||
>
|
||||
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
|
||||
<div class="flex flex-wrap">
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ recipeDetailForm.getRawValue().name }}
|
||||
</h5>
|
||||
<h5 class="mb-2 px-3 text-xl font-bold text-gray-900">|</h5>
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ recipeDetailForm.getRawValue().otherName }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<div class="flex items-center">
|
||||
<p class="text-sm text-gray-500">Last Modify</p>
|
||||
<p class="ml-2 text-sm text-gray-900">
|
||||
{{
|
||||
recipeDetailForm.getRawValue().lastModified
|
||||
| date : "dd/MM/yyyy HH:mm:ss"
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex p-3 items-center justify-center w-full">
|
||||
<img
|
||||
class="rounded-lg shadow"
|
||||
src="/assets/{{ 'bn_hot_america_no' }}.png"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="block col-span-2 p-6 bg-white border border-gray-200 rounded-lg shadow min-h-[300px]"
|
||||
>
|
||||
<div
|
||||
*ngIf="isLoaded; else indicator"
|
||||
[@inOutAnimation]
|
||||
class="grid-cols-2 w-full flex flex-col gap-2"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<label class="label text-base mr-3 w-max"
|
||||
><span class="label-text text-base mr-3 w-max">Name:</span></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="name"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label">
|
||||
<span class="label-text text-base mr-3 w-max"
|
||||
>Other Name:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="otherName"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label"
|
||||
><span class="lable-text text-base mr-3 w-max"
|
||||
>Description:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="Description"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<label class="label"
|
||||
><span class="label-text text-base mr-3 w-max"
|
||||
>Other Description:</span
|
||||
></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-sm input-bordered input-ghost w-full"
|
||||
formControlName="otherDescription"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-3 overflow-auto mb-4 rounded bg-white border border-gray-200 shadow"
|
||||
>
|
||||
<app-recipe-list
|
||||
[productCode]="productCode"
|
||||
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||
></app-recipe-list>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="sticky bottom-0 col-span-3 flex justify-end bg-white rounded-full drop-shadow-2xl p-3"
|
||||
>
|
||||
<!-- <div> Commit Message </div> -->
|
||||
<!-- <p class="text-2xl mr-8 text-gray-400 dark:text-gray-500">Commit Message</p> -->
|
||||
<input type="text" name="commit-message" id="commit-message" placeholder="Commit Message" class="input input-bordered mr-8 w-full max-w-xs" [value]="productCode" (keyup)="onKeyUpCommitMsg($event)"/>
|
||||
<button
|
||||
(click)="onPressConfirmClose()"
|
||||
class="btn btn-error w-36 text-white mr-2"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
(click)="onPressConfirmSave()"
|
||||
class="btn btn-success w-36 text-white"
|
||||
[disabled]="!isValueChanged"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<ng-template #indicator>
|
||||
<div class="flex w-full h-full justify-center items-center">
|
||||
<span class="loading loading-spinner w-20"></span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<confirm-modal
|
||||
[title]="confirmSave.title"
|
||||
[message]="confirmSave.message"
|
||||
[confirmCallBack]="confirmSave.confirmCallBack"
|
||||
[show]="showConfirmSaveModal"
|
||||
></confirm-modal>
|
||||
|
||||
<confirm-modal
|
||||
[title]="confirmClose.title"
|
||||
[message]="confirmClose.message"
|
||||
[confirmCallBack]="confirmClose.confirmCallBack"
|
||||
[show]="showConfirmCloseModal"
|
||||
></confirm-modal>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,158 +1,203 @@
|
|||
import { CommonModule, DatePipe } from '@angular/common';
|
||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Observable, first } 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 {
|
||||
RecipeDetail,
|
||||
RecipeDetailMat,
|
||||
} from 'src/app/core/models/recipe.model';
|
||||
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-details',
|
||||
templateUrl: './recipe-details.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterLink,
|
||||
ReactiveFormsModule,
|
||||
ConfirmModal,
|
||||
DatePipe,
|
||||
RecipeListComponent,
|
||||
],
|
||||
animations: [
|
||||
trigger('inOutAnimation', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0 }),
|
||||
animate('1s ease-out', style({ opacity: 1 })),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class RecipeDetailsComponent implements OnInit {
|
||||
title: string = 'Recipe Detail';
|
||||
|
||||
recipeDetail$!: Observable<RecipeDetail>;
|
||||
|
||||
isLoaded: boolean = false;
|
||||
isMatLoaded: boolean = false;
|
||||
|
||||
actionRecord: ActionRecord<RecipeDetail | RecipeDetailMat> =
|
||||
new ActionRecord();
|
||||
|
||||
recipeOriginalDetail!: typeof this.recipeDetailForm.value;
|
||||
|
||||
constructor(
|
||||
private _formBuilder: FormBuilder,
|
||||
private _route: ActivatedRoute,
|
||||
private _router: Router,
|
||||
private _recipeService: RecipeService
|
||||
) {}
|
||||
|
||||
productCode!: string;
|
||||
|
||||
recipeDetailForm = this._formBuilder.group({
|
||||
productCode: '',
|
||||
name: '',
|
||||
otherName: '',
|
||||
description: '',
|
||||
otherDescription: '',
|
||||
lastModified: new Date(),
|
||||
price: 0,
|
||||
isUse: false,
|
||||
isShow: false,
|
||||
disable: false,
|
||||
});
|
||||
|
||||
ngOnInit() {
|
||||
this.productCode = this._route.snapshot.params['productCode'];
|
||||
|
||||
this.recipeDetail$ = this._recipeService
|
||||
.getRecipeDetail(this.productCode)
|
||||
.pipe(first());
|
||||
this.recipeDetail$.subscribe((detail) => {
|
||||
this.recipeDetailForm.patchValue(detail);
|
||||
this.isLoaded = true;
|
||||
this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() };
|
||||
});
|
||||
|
||||
this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange);
|
||||
|
||||
// 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<boolean> = new EventEmitter<boolean>();
|
||||
showConfirmCloseModal: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
confirmSave = {
|
||||
title: 'The changes detected!',
|
||||
message: 'Do you want to save changes?',
|
||||
confirmCallBack: () => {
|
||||
console.log('confirm save');
|
||||
// TODO: update value in targeted recipe
|
||||
// this._recipeService.editChanges(
|
||||
// this._recipeService.getCurrentCountry(),
|
||||
// this._recipeService.getCurrentFile(),
|
||||
// {
|
||||
// ...this.recipeDetail,
|
||||
// }
|
||||
// );
|
||||
console.log('Sending changes');
|
||||
this._router.navigate(['/recipes']);
|
||||
},
|
||||
};
|
||||
|
||||
confirmClose = {
|
||||
title: 'The changes will be lost!',
|
||||
message: 'Do you want to close without saving?',
|
||||
confirmCallBack: () => {
|
||||
console.log('confirm close');
|
||||
this._router.navigate(['/recipes']);
|
||||
},
|
||||
};
|
||||
|
||||
onPressConfirmSave() {
|
||||
if (this.isValueChanged) {
|
||||
this.showConfirmSaveModal.emit(true);
|
||||
} else {
|
||||
this._router.navigate(['/recipes']);
|
||||
}
|
||||
}
|
||||
|
||||
onPressConfirmClose() {
|
||||
if (this.isValueChanged) {
|
||||
this.showConfirmCloseModal.emit(true);
|
||||
} else {
|
||||
this._router.navigate(['/recipes']);
|
||||
}
|
||||
}
|
||||
|
||||
isValueChanged: boolean = false;
|
||||
|
||||
onRecipeDetailFormChange(recipeDetail: typeof this.recipeDetailForm.value) {
|
||||
console.log('Recipe Detail Form Changed', recipeDetail);
|
||||
}
|
||||
|
||||
onRecipeListFormChange(isValueChanged: boolean) {
|
||||
console.log('Recipe List Form Changed', isValueChanged);
|
||||
this.isValueChanged ||= isValueChanged;
|
||||
}
|
||||
}
|
||||
import { CommonModule, DatePipe } from '@angular/common';
|
||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Observable, first } 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 {
|
||||
RecipeDetail,
|
||||
RecipeDetailMat,
|
||||
} from 'src/app/core/models/recipe.model';
|
||||
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
||||
import { isEqual } from 'lodash';
|
||||
import { UserService } from 'src/app/core/services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-details',
|
||||
templateUrl: './recipe-details.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterLink,
|
||||
ReactiveFormsModule,
|
||||
ConfirmModal,
|
||||
DatePipe,
|
||||
RecipeListComponent,
|
||||
],
|
||||
animations: [
|
||||
trigger('inOutAnimation', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0 }),
|
||||
animate('1s ease-out', style({ opacity: 1 })),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class RecipeDetailsComponent implements OnInit {
|
||||
title: string = 'Recipe Detail';
|
||||
|
||||
recipeDetail$!: Observable<RecipeDetail>;
|
||||
|
||||
isLoaded: boolean = false;
|
||||
isMatLoaded: boolean = false;
|
||||
|
||||
actionRecord: ActionRecord<RecipeDetail | RecipeDetailMat> =
|
||||
new ActionRecord();
|
||||
|
||||
recipeOriginalDetail!: typeof this.recipeDetailForm.value;
|
||||
|
||||
commit_msg :string = "";
|
||||
|
||||
constructor(
|
||||
private _formBuilder: FormBuilder,
|
||||
private _route: ActivatedRoute,
|
||||
private _router: Router,
|
||||
private _recipeService: RecipeService,
|
||||
private _userService: UserService
|
||||
) {}
|
||||
|
||||
productCode!: string;
|
||||
|
||||
recipeDetailForm = this._formBuilder.group({
|
||||
productCode: '',
|
||||
name: '',
|
||||
otherName: '',
|
||||
Description: '',
|
||||
otherDescription: '',
|
||||
lastModified: new Date(),
|
||||
price: 0,
|
||||
isUse: false,
|
||||
isShow: false,
|
||||
disable: false,
|
||||
});
|
||||
|
||||
repl = []
|
||||
|
||||
ngOnInit() {
|
||||
this.productCode = this._route.snapshot.params['productCode'];
|
||||
|
||||
this.recipeDetail$ = 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.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange);
|
||||
|
||||
// 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<boolean> = new EventEmitter<boolean>();
|
||||
showConfirmCloseModal: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
confirmSave = {
|
||||
title: 'The changes detected!',
|
||||
message: 'Do you want to save changes?',
|
||||
confirmCallBack: () => {
|
||||
console.log('confirm save');
|
||||
|
||||
// get username
|
||||
let username:string = ""
|
||||
this._userService.getCurrentUser().subscribe((user) => {
|
||||
username = user.user.name;
|
||||
|
||||
|
||||
|
||||
let to_send = {
|
||||
edit_by: username,
|
||||
commit_msg: this.commit_msg,
|
||||
productCode: this.productCode,
|
||||
name: this.recipeDetailForm.getRawValue().name,
|
||||
otherName: this.recipeDetailForm.getRawValue().otherName,
|
||||
Description: this.recipeDetailForm.getRawValue().Description,
|
||||
otherDescription: this.recipeDetailForm.getRawValue().otherDescription,
|
||||
LastChange: this.recipeDetailForm.getRawValue().lastModified,
|
||||
price: this.recipeDetailForm.getRawValue().price,
|
||||
// isUse: this,
|
||||
// isShow: null,
|
||||
// disable: null,
|
||||
recipes: [
|
||||
...this.repl
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
// TODO: update value in targeted recipe
|
||||
this._recipeService.editChanges(
|
||||
this._recipeService.getCurrentCountry(),
|
||||
this._recipeService.getCurrentFile(),
|
||||
{
|
||||
...to_send,
|
||||
}
|
||||
);
|
||||
console.log('Sending changes');
|
||||
this._router.navigate(['/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(['/recipes']);
|
||||
},
|
||||
};
|
||||
|
||||
onPressConfirmSave() {
|
||||
if (this.isValueChanged) {
|
||||
this.showConfirmSaveModal.emit(true);
|
||||
} else {
|
||||
this._router.navigate(['/recipes']);
|
||||
}
|
||||
}
|
||||
|
||||
onPressConfirmClose() {
|
||||
if (this.isValueChanged) {
|
||||
this.showConfirmCloseModal.emit(true);
|
||||
} else {
|
||||
this._router.navigate(['/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 as never[];
|
||||
this.isValueChanged ||= repl != undefined ? true : false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +1,57 @@
|
|||
<table class="table" [formGroup]="recipeListForm">
|
||||
<thead>
|
||||
<tr class="bg-gray-200">
|
||||
<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 Name</th>
|
||||
<th class="px-6 py-3">MixOrder</th>
|
||||
<th class="px-6 py-3">Stir Time</th>
|
||||
<th class="px-6 py-3">Powder Gram</th>
|
||||
<th class="px-6 py-3">Powder Time</th>
|
||||
<th class="px-6 py-3">Syrup Gram</th>
|
||||
<th class="px-6 py-3">Syrup Time</th>
|
||||
<th class="px-6 py-3">Water Cold</th>
|
||||
<th class="px-6 py-3">Water Yield</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
formArrayName="recipeListData"
|
||||
*ngFor="let mat of recipeListData.controls; let i = index"
|
||||
>
|
||||
<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">
|
||||
<input type="checkbox" class="toggle" formControlName="isUse" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="materialID" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="name" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="mixOrder" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="powderGram" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="powderTime" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="syrupGram" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="syrupTime" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="waterCold" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="waterYield" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="stirTime" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table" [formGroup]="recipeListForm">
|
||||
<thead>
|
||||
<tr class="bg-gray-200">
|
||||
<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 Name</th>
|
||||
<th class="px-6 py-3">MixOrder</th>
|
||||
<th class="px-6 py-3">Stir Time</th>
|
||||
<th class="px-6 py-3">Powder Gram</th>
|
||||
<th class="px-6 py-3">Powder Time</th>
|
||||
<th class="px-6 py-3">Syrup Gram</th>
|
||||
<th class="px-6 py-3">Syrup Time</th>
|
||||
<th class="px-6 py-3">Water Cold</th>
|
||||
<th class="px-6 py-3">Water Yield</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
formArrayName="recipeListData"
|
||||
*ngFor="let mat of recipeListData.controls; let i = index"
|
||||
>
|
||||
<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">
|
||||
<input type="checkbox" class="toggle" formControlName="isUse" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="materialPathId" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="name" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="mixOrder" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="powderGram" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="powderTime" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="syrupGram" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="syrupTime" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="waterCold" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="waterYield" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<input type="text" class="input" formControlName="stirTime" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -1,90 +1,102 @@
|
|||
import { NgFor, NgIf } from '@angular/common';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
FormArray,
|
||||
FormBuilder,
|
||||
FormControl,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { isEqual, sortBy } from 'lodash';
|
||||
import { first } from 'rxjs';
|
||||
import {
|
||||
RecipeDetail,
|
||||
RecipeDetailMat,
|
||||
} from 'src/app/core/models/recipe.model';
|
||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-list',
|
||||
templateUrl: './recipe-list.component.html',
|
||||
standalone: true,
|
||||
imports: [NgIf, NgFor, ReactiveFormsModule],
|
||||
})
|
||||
export class RecipeListComponent implements OnInit {
|
||||
@Input({ required: true }) productCode!: string;
|
||||
@Output() recipeListFormChange = new EventEmitter<boolean>();
|
||||
|
||||
isMatLoaded: boolean = false;
|
||||
|
||||
constructor(
|
||||
private _recipeService: RecipeService,
|
||||
private _formBuilder: FormBuilder
|
||||
) {}
|
||||
|
||||
recipeListForm = this._formBuilder.group(
|
||||
{
|
||||
recipeListData: this._formBuilder.array([]),
|
||||
},
|
||||
{ updateOn: 'blur' }
|
||||
);
|
||||
|
||||
private _recipeListOriginalArray!: RecipeDetailMat[];
|
||||
|
||||
ngOnInit(): void {
|
||||
this._recipeService
|
||||
.getRecipeDetailMat(this.productCode)
|
||||
.pipe(first())
|
||||
.subscribe(({ result }) => {
|
||||
this._recipeListOriginalArray = result;
|
||||
result.forEach((recipeDetailMat: RecipeDetailMat) => {
|
||||
this.recipeListData.push(
|
||||
this._formBuilder.group({
|
||||
isUse: recipeDetailMat.isUse,
|
||||
materialID: recipeDetailMat.materialID,
|
||||
name: [{ value: recipeDetailMat.name, disabled: true }],
|
||||
mixOrder: recipeDetailMat.mixOrder,
|
||||
stirTime: recipeDetailMat.stirTime,
|
||||
powderGram: recipeDetailMat.powderGram,
|
||||
powderTime: recipeDetailMat.powderTime,
|
||||
syrupGram: recipeDetailMat.syrupGram,
|
||||
syrupTime: recipeDetailMat.syrupTime,
|
||||
waterCold: recipeDetailMat.waterCold,
|
||||
waterYield: recipeDetailMat.waterYield,
|
||||
})
|
||||
);
|
||||
});
|
||||
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 {
|
||||
return this.recipeListForm.get('recipeListData') as FormArray;
|
||||
}
|
||||
}
|
||||
import { NgFor, NgIf } from '@angular/common';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
FormArray,
|
||||
FormBuilder,
|
||||
FormControl,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { forEach, isEqual, sortBy } from 'lodash';
|
||||
import { first } from 'rxjs';
|
||||
import {
|
||||
RecipeDetail,
|
||||
RecipeDetailMat,
|
||||
} from 'src/app/core/models/recipe.model';
|
||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||
import { Action, ActionRecord } from 'src/app/shared/actionRecord/actionRecord';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recipe-list',
|
||||
templateUrl: './recipe-list.component.html',
|
||||
standalone: true,
|
||||
imports: [NgIf, NgFor, ReactiveFormsModule],
|
||||
})
|
||||
export class RecipeListComponent implements OnInit {
|
||||
@Input({ required: true }) productCode!: string;
|
||||
@Output() recipeListFormChange = new EventEmitter<unknown[]>();
|
||||
|
||||
isMatLoaded: boolean = false;
|
||||
|
||||
constructor(
|
||||
private _recipeService: RecipeService,
|
||||
private _formBuilder: FormBuilder
|
||||
) {}
|
||||
|
||||
recipeListForm = this._formBuilder.group(
|
||||
{
|
||||
recipeListData: this._formBuilder.array([]),
|
||||
},
|
||||
{ updateOn: 'blur' }
|
||||
);
|
||||
|
||||
private _recipeListOriginalArray!: RecipeDetailMat[];
|
||||
|
||||
ngOnInit(): void {
|
||||
this._recipeService
|
||||
.getRecipeDetailMat(this.productCode)
|
||||
.pipe(first())
|
||||
.subscribe(({ result }) => {
|
||||
this._recipeListOriginalArray = result;
|
||||
result.forEach((recipeDetailMat: RecipeDetailMat) => {
|
||||
this.recipeListData.push(
|
||||
this._formBuilder.group({
|
||||
isUse: recipeDetailMat.isUse,
|
||||
materialPathId: recipeDetailMat.materialPathId,
|
||||
name: [{ value: recipeDetailMat.name, disabled: true }],
|
||||
mixOrder: recipeDetailMat.mixOrder,
|
||||
stirTime: recipeDetailMat.stirTime,
|
||||
powderGram: recipeDetailMat.powderGram,
|
||||
powderTime: recipeDetailMat.powderTime,
|
||||
syrupGram: recipeDetailMat.syrupGram,
|
||||
syrupTime: recipeDetailMat.syrupTime,
|
||||
waterCold: recipeDetailMat.waterCold,
|
||||
waterYield: recipeDetailMat.waterYield,
|
||||
})
|
||||
);
|
||||
});
|
||||
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')
|
||||
)
|
||||
) {
|
||||
|
||||
let emitted_res: any[] = []
|
||||
|
||||
// force type change. temporary solution
|
||||
forEach(value.recipeListData!, (recipeDetailMat: any) => {
|
||||
recipeDetailMat.materialPathId = parseInt(recipeDetailMat.materialPathId!)
|
||||
emitted_res.push(recipeDetailMat)
|
||||
})
|
||||
|
||||
this.recipeListFormChange.emit(emitted_res as unknown[]);
|
||||
} else {
|
||||
this.recipeListFormChange.emit([]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
get recipeListData(): FormArray {
|
||||
return this.recipeListForm.get('recipeListData') as FormArray;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue