[init] init version

This commit is contained in:
2023-10-10 03:58:47 +07:00
commit 73359d5f24
299 changed files with 55909 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CustomerIndexComponent } from './index/customer-index.component';
import {CustomerDoComponent} from "./do/customer-do.component";
import {CustomerImportComponent} from "./import/customer-import.component";
const routes: Routes = [
{path: '', component: CustomerIndexComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomerRoutingModule { }
export const RoutingComponents = [
CustomerIndexComponent,
CustomerDoComponent,
CustomerImportComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, CustomerRoutingModule} from './customer-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
CustomerRoutingModule
],
})
export class CustomerModule {}

View File

@@ -0,0 +1,136 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-2 md:col-span-12 ">
<mat-label>รหัสลูกค้า</mat-label>
<mat-form-field>
<input matInput name="code" #code="ngModel" [(ngModel)]="dataForm.code" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12 ">
<mat-label>คำนำหน้า</mat-label>
<ng-select placeholder="เลือกคำนำหน้า" name="prefix" #prefix="ngModel" [(ngModel)]="dataForm.prefix" appendTo="body" required>
<ng-option *ngFor="let item of prefixData" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>ชื่อ</mat-label>
<mat-form-field>
<input matInput name="firstName" #firstName="ngModel" [(ngModel)]="dataForm.firstName" required>
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>นามสกุล</mat-label>
<mat-form-field>
<input matInput name="lastName" #lastName="ngModel" [(ngModel)]="dataForm.lastName" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12 ">
<mat-label>เพศ</mat-label>
<ng-select placeholder="เลือกเพศ" name="gender" #gender="ngModel" [(ngModel)]="dataForm.gender" appendTo="body" required>
<ng-option *ngFor="let item of genderData" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>เบอร์โทร</mat-label>
<mat-form-field>
<input matInput name="phone" #phone="ngModel" [(ngModel)]="dataForm.phone" required>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>เลขบัตรประชาชน/เลขประจําตัวผู้เสียภาษี</mat-label>
<mat-form-field>
<input matInput name="idCard" #idCard="ngModel" [(ngModel)]="dataForm.idCard" required>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<div style="height: 20px;"></div>
<div class="flex items-center">
<div class="">
<input hidden type="file" accept="image/*" #idCardImages (change)="onAttachments($event, 'idcard')" />
<button type="button" class="btn btn-icon-upload color-main" (click)="idCardImages.click()">
<ng-container *ngIf="!dataForm.idCardImage"> <i class="bi bi-plus-circle "></i> สำเนาบัตรประชาชน</ng-container>
<ng-container *ngIf="dataForm.idCardImage"> <i class="bi bi-pencil" matTooltip="แก้ไขสำเนาบัตรประชาชน"></i> </ng-container>
</button>
</div>
<div style="padding-top: 4px;">
<ng-container *ngIf="dataForm.idCardImage">
<div class="cursor-pointer" (click)="onAttachmentsView('images')"><i class="bi bi-search"></i> ดูสำเนาบัตรประชาชน</div></ng-container>
</div>
</div>
</div>
<div class="col-span-8 md:hidden"></div>
<div class="col-span-12 md:col-span-12 ">
<mat-label>ที่อยู่ตามบัตรประชาชน</mat-label>
<mat-form-field>
<input matInput name="address" #address="ngModel" [(ngModel)]="dataForm.address" (ngModelChange)="onChangeAddress('address', $event)">
</mat-form-field>
</div>
<div class="col-span-12 md:col-span-12 ">
<mat-label>ที่อยู่ในการจัดส่ง</mat-label>
<label class="inline-flex items-center cursor-pointer select-none ml-2">
<input type="checkbox" name="isAddress" [(ngModel)]="dataForm.isAddress" (ngModelChange)="onChangeAddress('isAddress', $event)" >
<span style="padding-left: 2px;">ใช้ที่อยู่ตามบัตรประชาชน</span>
</label>
<mat-form-field>
<input matInput name="deliveryAddress" #deliveryAddress="ngModel" [(ngModel)]="dataForm.deliveryAddress" [disabled]="dataForm.isAddress">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>E-mail</mat-label>
<mat-form-field>
<input matInput name="email" #email="ngModel" [(ngModel)]="dataForm.email">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>อาชีพ</mat-label>
<mat-form-field>
<input matInput name="occupation" #occupation="ngModel" [(ngModel)]="dataForm.occupation">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>ID Line</mat-label>
<mat-form-field>
<input matInput name="line" #line="ngModel" [(ngModel)]="dataForm.line">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>ID Line Shop</mat-label>
<mat-form-field>
<input matInput name="lineShop" #lineShop="ngModel" [(ngModel)]="dataForm.lineShop">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>Facebook</mat-label>
<mat-form-field>
<input matInput name="facebook" #facebook="ngModel" [(ngModel)]="dataForm.facebook">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>IG</mat-label>
<mat-form-field>
<input matInput name="ig" #ig="ngModel" [(ngModel)]="dataForm.ig">
</mat-form-field>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,115 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import { API, EAction, EText, GENDER, PREFIX } from "../../../../@config/app";
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
import deepCopy from "../../../../@common/utils/DeepCopy";
import { AttachmentsViewComponent } from "../../../@popup/attachments-view/attachments-view.component";
@Component({
selector: 'app-customer-do',
templateUrl: './customer-do.component.html',
styleUrls: []
})
export class CustomerDoComponent extends BasePopupComponent implements OnInit {
title = 'ลูกค้า/ร้านค้า';
apiUrl: string = API.customer;
genderData = GENDER;
prefixData = PREFIX;
constructor(
public dialogRef: MatDialogRef<CustomerDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
private attachments: MatDialog,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
if (this.dataForm.isAddress) this.dataForm.deliveryAddress = this.dataForm.address;
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dataForm.isAddress) this.dataForm.deliveryAddress = this.dataForm.address;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
onChangeAddress(key : string, value : any) {
if (key === 'isAddress') this.dataForm.deliveryAddress = value ? this.dataForm.address : '';
if (key === 'address') this.dataForm.deliveryAddress = this.dataForm.isAddress ? value : this.dataForm.deliveryAddress;
}
async onAttachments($event: any, type: any) {
const file = $event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append("ref", type);
formData.append("file", file);
try {
const res = await lastValueFrom(this.appService.post(`${API.attachments}/images`, formData));
this.dataForm.idCardImage = res.fileName;
this.changeDetectorRef.detectChanges();
} catch (e) {
this.appService.message(EText.ERROR);
}
}
async onAttachmentsView(type : any) {
const dialogConfig = deepCopy(this.dialogConfig);
dialogConfig.data.action = EAction.POPUP;
dialogConfig.data.title = 'สำเนาบัตรประชาชน';
dialogConfig.data.type = type;
dialogConfig.data.images = this.dataForm.idCardImage;
const dialogRef = this.attachments.open(AttachmentsViewComponent, dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
}
}

View File

@@ -0,0 +1,37 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body !pb-0" >
<div style="height: 20px;"></div>
<div class="upload-wrap" (click)="files.click()">
<div class="">อัปโหลด Excel....</div>
<input
hidden
type="file"
accept="application/vnd.ms-excel,.xls,.xlsx,.csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xls,.xlsx,.csv,application/vnd.openxmlformats-officedocument.spreadsheetml.template,.xls,.xlsx,.csv,text/csv,.xls,.xlsx,.csv"
#files (change)="onImport($event)" />
</div>
<div class="upload-detail">
<ng-container *ngIf="dataFile?.name">
<div class="upload-detail-item">
<i class="bi bi-filetype-xlsx"></i> {{dataFile?.name}}
</div>
</ng-container>
</div>
<!-- <div class="upload-template">-->
<!-- <a (click)="onDownloadTemplate()"> ดาวน์โหลด Template สำหรับนำเข้ารายการสินค้า</a>-->
<!-- </div>-->
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit">นำเข้าข้อมูล</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,72 @@
import { ChangeDetectorRef, Component, Inject, OnInit } from "@angular/core";
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
import { BasePopupComponent } from "../../../../@common/base/base-popup.component";
import { API, EAction, EText } from "../../../../@config/app";
import { IDialogConfigData } from "../../../../@common/interface/Dialog";
import { AppService } from "../../../../app.service";
import { lastValueFrom } from "rxjs";
import { Router } from "@angular/router";
@Component({
selector: "app-customer-import",
templateUrl: "./customer-import.component.html",
styleUrls: []
})
export class CustomerImportComponent extends BasePopupComponent implements OnInit {
title = "นำเข้าลูกค้า/ร้านค้า";
api = API;
dataFile: any;
constructor(
public dialogRef: MatDialogRef<CustomerImportComponent>,
@Inject(MAT_DIALOG_DATA) public dialog: IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
public router: Router,
) {
super();
}
async ngOnInit() {
}
async onImport($event: any) {
const file = $event.target.files[0];
if (!file) return;
try {
this.dataFile = file;
this.changeDetectorRef.detectChanges();
} catch (e) {
this.appService.message(EText.ERROR);
}
}
onDownloadTemplate() {
const url = `${this.api.url}/template/products-template.xlsx`;
window.open(url);
}
async onSubmit(form: any) {
if (!this.dataFile) return this.appService.message('กรุณาอัปโหลด Excel');
try {
const formData = new FormData();
formData.append("file", this.dataFile);
await lastValueFrom(this.appService.post(`${this.api.customer}/import`, formData));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
this.dialogRef.close(EAction.GET);
} catch (e) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,90 @@
<div class="card card-table">
<div class="card-filter text-right">
<div class="card-filter-section grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-5 md:col-span-12 md:order-2">
<mat-form-field>
<i matTextPrefix class="bi bi-search"></i>
<input matInput name="keyword" #keyword="ngModel" [(ngModel)]="dataFilter.keyword" (ngModelChange)="onFilter($event)">
</mat-form-field>
</div>
<div class="col-span-7 md:col-span-12 md:order-1">
<div class="card-header-action">
<button type="button" class="btn btn-export" (click)="onExport()">Export</button>
<button type="button" class="btn btn-import" (click)="onImport()">Import</button>
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
</div>
</div>
</div>
<div class="card-body">
<div class="table-wrap">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tal">รหัส</th>
<td mat-cell *matCellDef="let item" style="min-width: 150px !important;">{{item.code }}</td>
</ng-container>
<ng-container matColumnDef="idCard">
<th mat-header-cell *matHeaderCellDef class="tal">เลขบัตรประจำตัวประชาชน <br>/เลขประจําตัวผู้เสียภาษี</th>
<td mat-cell *matCellDef="let item" style="min-width: 150px !important;">{{item.idCard }}</td>
</ng-container>
<ng-container matColumnDef="firstName">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ</th>
<td mat-cell *matCellDef="let item" style="min-width: 200px;">{{item.prefix }} {{item.firstName }} {{item.lastName }}</td>
</ng-container>
<ng-container matColumnDef="phone">
<th mat-header-cell *matHeaderCellDef class="tal">เบอร์โทร</th>
<td mat-cell *matCellDef="let item" class="">{{item.phone }}</td>
</ng-container>
<ng-container matColumnDef="line">
<th mat-header-cell *matHeaderCellDef class="tal">ID Line</th>
<td mat-cell *matCellDef="let item" class="">{{item.line }}</td>
</ng-container>
<ng-container matColumnDef="facebook">
<th mat-header-cell *matHeaderCellDef class="tal">Facebook</th>
<td mat-cell *matCellDef="let item" class="">{{item.facebook }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
</div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,93 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {debounceTime, distinctUntilChanged, lastValueFrom, Subject} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {CustomerDoComponent} from "../do/customer-do.component";
import generateParamsValue from "../../../../@common/utils/GenerateParamsValue";
import deepCopy from "../../../../@common/utils/DeepCopy";
import {ProductImportComponent} from "../../products/import/product-import.component";
import {CustomerImportComponent} from "../import/customer-import.component";
@Component({
selector: 'app-customer-index',
templateUrl: './customer-index.component.html',
styleUrls: []
})
export class CustomerIndexComponent extends BaseListComponent implements OnInit {
pageTitle = 'ลูกค้า/ร้านค้า';
apiUrl: string = API.customer;
displayedColumns: string[] = ['action', 'code', 'idCard', 'firstName','phone','line','facebook'];
filterKeyword: Subject<string> = new Subject<string>();
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
this.filterKeyword.pipe(debounceTime(1000), distinctUntilChanged()).subscribe(model => {
this.getData();
});
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
this.dataFilter.keywordColumn = 'code,idCard,firstName,phone,line,facebook';
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter($event? : any) {
this.filterKeyword.next($event);
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(CustomerDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onExport() {
const filter = generateParamsValue(this.dataFilter);
const url = `${API.customer}/export?${filter ? '&' + filter : '' }`;
window.open(url);
}
async onImport() {
const dialogConfig = deepCopy(this.dialogConfig);
dialogConfig.width = '50%';
dialogConfig.height = '50%';
dialogConfig.data.action = EAction.POPUP;
const dialogRef = this.dialog.open(CustomerImportComponent, dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
}

View File

@@ -0,0 +1,65 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-4 md:col-span-12">
<mat-label>รหัสคลังสินค้า</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12">
<mat-label>ชื่อคลังสินค้า</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-label>ชื่อห้อง</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.roomName" name="roomName" #roomName="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, roomName)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:hidden"></div>
<div class="col-span-8 md:col-span-12">
<mat-label>สถานที่</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.location" name="location" #location="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, location)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-label>ชั้นที่</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.floor" name="floor" #floor="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, floor)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:hidden"></div>
<div class="col-span-4 md:col-span-12">
<mat-label>ขนาดห้อง (ลูกบาศก์)</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.roomSize" name="roomSize" #roomSize="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, roomSize)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-8 md:hidden"></div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status" >สถานะ</mat-slide-toggle>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit" >บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,73 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import {API, EAction, EText} from "../../../../@config/app";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
@Component({
selector: 'app-master-area-do',
templateUrl: './master-area-do.component.html',
styleUrls: []
})
export class MasterAreaDoComponent extends BasePopupComponent implements OnInit {
title = 'กำหนดคลังสินค้า';
apiUrl: string = API.masterArea;
constructor(
public dialogRef: MatDialogRef<MasterAreaDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
}

View File

@@ -0,0 +1,79 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<div class="table-wrap">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัสคลังสินค้า</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อคลัง</th>
<td mat-cell *matCellDef="let item" style="min-width: 150px !important;">{{item.name }}</td>
</ng-container>
<ng-container matColumnDef="roomName">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อห้อง</th>
<td mat-cell *matCellDef="let item" style="min-width: 150px !important;">{{item.roomName }}</td>
</ng-container>
<ng-container matColumnDef="location">
<th mat-header-cell *matHeaderCellDef class="tal">สถานที่</th>
<td mat-cell *matCellDef="let item" style="min-width: 200px;">{{item.location }}</td>
</ng-container>
<ng-container matColumnDef="floor">
<th mat-header-cell *matHeaderCellDef class="tal">ชั้น</th>
<td mat-cell *matCellDef="let item" class="">{{item.floor }}</td>
</ng-container>
<ng-container matColumnDef="roomSize">
<th mat-header-cell *matHeaderCellDef class="tal">ขนาดห้อง (ลูกบาศก์)</th>
<td mat-cell *matCellDef="let item" class="">{{item.roomSize }}</td>
</ng-container>
<ng-container matColumnDef="remainingSpace">
<th mat-header-cell *matHeaderCellDef class="tal">พื้นที่คงเหลือ (ลูกบาศก์)</th>
<td mat-cell *matCellDef="let item" class="">{{item.remainingSpace }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
</div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {lastValueFrom} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {MasterAreaDoComponent} from "../do/master-area-do.component";
@Component({
selector: 'app-master-area-index',
templateUrl: './master-area-index.component.html',
styleUrls: []
})
export class MasterAreaIndexComponent extends BaseListComponent implements OnInit {
pageTitle = 'กำหนดคลังสินค้า';
apiUrl: string = API.masterArea;
displayedColumns: string[] = ['action', 'code', 'name','roomName','location','floor','roomSize','remainingSpace', 'status'];
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(MasterAreaDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MasterAreaIndexComponent } from './index/master-area-index.component';
import {MasterAreaDoComponent} from "./do/master-area-do.component";
const routes: Routes = [
{path: '', component: MasterAreaIndexComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterAreaRoutingModule { }
export const RoutingComponents = [
MasterAreaIndexComponent,
MasterAreaDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, MasterAreaRoutingModule} from './master-area-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
MasterAreaRoutingModule
],
})
export class MasterAreaModule {}

View File

@@ -0,0 +1,36 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส{{title}}</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ{{title}}</mat-label>
<mat-form-field>
<textarea matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required></textarea>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status" >สถานะ</mat-slide-toggle>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit" >บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,73 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import {API, EAction, EText} from "../../../../@config/app";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
@Component({
selector: 'app-master-product-brand-do',
templateUrl: './master-product-brand-do.component.html',
styleUrls: []
})
export class MasterProductBrandDoComponent extends BasePopupComponent implements OnInit {
title = 'Brand';
apiUrl: string = API.masterProductBrand;
constructor(
public dialogRef: MatDialogRef<MasterProductBrandDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {lastValueFrom} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {MasterProductBrandDoComponent} from "../do/master-product-brand-do.component";
@Component({
selector: 'app-master-product-brand-index',
templateUrl: './master-product-brand.component.html',
styleUrls: []
})
export class MasterProductBrandComponent extends BaseListComponent implements OnInit {
pageTitle = 'Brand';
apiUrl: string = API.masterProductBrand;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(MasterProductBrandDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MasterProductBrandComponent } from './index/master-product-brand.component';
import {MasterProductBrandDoComponent} from "./do/master-product-brand-do.component";
const routes: Routes = [
{path: '', component: MasterProductBrandComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterProductBrandRoutingModule { }
export const RoutingComponents = [
MasterProductBrandComponent,
MasterProductBrandDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, MasterProductBrandRoutingModule} from './master-product-brand-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
MasterProductBrandRoutingModule
],
})
export class MasterProductBrandModule {}

View File

@@ -0,0 +1,36 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส{{title}}</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ{{title}}</mat-label>
<mat-form-field>
<textarea matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required></textarea>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status" >สถานะ</mat-slide-toggle>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit" >บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,73 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import {API, EAction, EText} from "../../../../@config/app";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
@Component({
selector: 'app-master-product-category-do',
templateUrl: './master-product-category-do.component.html',
styleUrls: []
})
export class MasterProductCategoryDoComponent extends BasePopupComponent implements OnInit {
title = 'หมวดหมู่';
apiUrl: string = API.masterProductCategory;
constructor(
public dialogRef: MatDialogRef<MasterProductCategoryDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onPopup()">
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {lastValueFrom} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {MasterProductCategoryDoComponent} from "../do/master-product-category-do.component";
@Component({
selector: 'app-master-product-category-index',
templateUrl: './master-product-category.component.html',
styleUrls: []
})
export class MasterProductCategoryComponent extends BaseListComponent implements OnInit {
pageTitle = 'หมวดหมู่';
apiUrl: string = API.masterProductCategory;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(MasterProductCategoryDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MasterProductCategoryComponent } from './index/master-product-category.component';
import {MasterProductCategoryDoComponent} from "./do/master-product-category-do.component";
const routes: Routes = [
{path: '', component: MasterProductCategoryComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterProductCategoryRoutingModule { }
export const RoutingComponents = [
MasterProductCategoryComponent,
MasterProductCategoryDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, MasterProductCategoryRoutingModule} from './master-product-category-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
MasterProductCategoryRoutingModule
],
})
export class MasterProductCategoryModule {}

View File

@@ -0,0 +1,92 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="card card-form-panel ">
<div class="card-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ{{title}}</mat-label>
<mat-form-field>
<textarea matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required></textarea>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status">สถานะ</mat-slide-toggle>
</div>
</div>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-3 md:col-span-12"> รูปแบบการวัด</div>
<div class="col-span-9 md:col-span-12 ">
<form class="mt-2" #ngf2="ngForm" (ngSubmit)="onAddItem(ngf2)">
<div class="form-list-action flex items-center justify-end md:justify-start">
<div class=""> ระบุจำนวนการวัด (จุด)</div>
<div class="ml-2 mr-2">
<mat-form-field>
<input matInput appNumberOnly name="addItemNum" #addItemNum="ngModel" [(ngModel)]="addItemNumber" required>
</mat-form-field>
</div>
<div class="">
<button type="submit" class="btn btn-primary"> เพิ่ม</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm.productMeasurement; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-7 md:col-span-11">
<label *ngIf="i === 0">รายการวัด</label>
<mat-form-field>
<input matInput name="productMeasurementName-{{i}}" #productMeasurementName="ngModel" [(ngModel)]="item.name" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">ขนาด</label>
<mat-form-field>
<input appNumberOnly matInput name="productMeasurementSize-{{i}}" #productMeasurementSize="ngModel" [(ngModel)]="item.size" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-5">
<label *ngIf="i === 0">หน่วยนับ</label>
<ng-select placeholder="เลือกหน่วยนับ" name="productMeasurementUnit-{{i}}" #productMeasurementUnit="ngModel" [(ngModel)]="item.unitId" appendTo="body" required>
<ng-option *ngFor="let item of masterProductUnit" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
<div class="col-span-1 md:col-span-1 text-center">
<div *ngIf="i === 0" style="height: 25px;"></div>
<i *ngIf="i !== 0" (click)="onRemoveItem(i)" class="bi bi-x-circle color-red cursor-pointer select-none"></i>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="main-form-action text-right">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" class="btn btn-back" (click)="onAction('back')">ยกเลิก</button>
</div>
</form>

View File

@@ -0,0 +1,113 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { API, EAction, EText } from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { BasePopupComponent } from "../../../../@common/base/base-popup.component";
import { lastValueFrom } from "rxjs";
import { IProductMeasurement } from "../../../../app.interface";
import { ActivatedRoute, Router } from "@angular/router";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
@Component({
selector: "app-product-do",
templateUrl: "./master-product-measurement-do.component.html",
styleUrls: []
})
export class MasterProductMeasurementDoComponent extends BaseFormComponent implements OnInit {
title = "รูปแบบการวัด";
api: any = API;
addItemNumber: number = 1;
masterProductUnit: any = [];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.activatedRoute.params.subscribe(async params => {
this.ids = params["id"];
this.action = params["action"];
this.masterProductUnit = await lastValueFrom(this.appService.get(`${this.api.masterProductUnit}?showAll=true&status=true&orderBy=name&sort=asc`));
if (!this.dataForm.productMeasurement?.[0]) {
this.dataForm.productMeasurement = [
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{}
];
}
if (this.ids) await this.getData();
});
}
async onAction(action: string) {
if (action === "back") return this.router.navigate(["/pages/setting/product-measurement"]);
return;
}
async getData() {
if (!this.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.masterProductMeasurement}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
if (this.action === EAction.CREATE) return await this.onCreate();
if (this.action === EAction.UPDATE) return await this.onUpdate();
return;
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.api.masterProductMeasurement, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.onAction('back')
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.api.masterProductMeasurement}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.onAction('back')
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onAddItem(form: any) {
if (!form.valid) return false;
for (let i = 0; i < this.addItemNumber; i++) {
this.dataForm.productMeasurement?.push(<IProductMeasurement>{});
}
return;
}
onRemoveItem(i: number) {
console.log(this.dataForm.productMeasurement?.[i]);
this.dataForm.productMeasurement?.splice(i, 1);
this.changeDetectorRef.detectChanges();
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onAction()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BaseListComponent } from "../../../../@common/base/base-list.component";
import { lastValueFrom } from "rxjs";
import { AppService } from "../../../../app.service";
import { API, EAction, EText } from "../../../../@config/app";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-product-index",
templateUrl: "./master-product-measurement.component.html",
styleUrls: []
})
export class MasterProductMeasurementComponent extends BaseListComponent implements OnInit {
pageTitle = "รูปแบบการวัด";
apiUrl: string = API.masterProductMeasurement;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public appService: AppService
) {
super();
}
async ngOnInit() {
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(["/pages/setting/product-measurement/do", "update", id]);
return this.router.navigate(["/pages/setting/product-measurement/do", "create"]);
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,22 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {MasterProductMeasurementComponent} from './index/master-product-measurement.component';
import {MasterProductMeasurementDoComponent} from "./do/master-product-measurement-do.component";
const routes: Routes = [
{path: '', component: MasterProductMeasurementComponent},
{path: 'do/:action', component: MasterProductMeasurementDoComponent},
{path: 'do/:action/:id', component: MasterProductMeasurementDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterProductMeasurementRoutingModule {
}
export const ProductRoutingComponents = [
MasterProductMeasurementComponent,
MasterProductMeasurementDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {ProductRoutingComponents, MasterProductMeasurementRoutingModule} from './master-product-measurement-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...ProductRoutingComponents,
],
imports: [
AppSharedModule,
MasterProductMeasurementRoutingModule
],
})
export class MasterProductMeasurementModule {}

View File

@@ -0,0 +1,36 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส{{title}}</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ{{title}}</mat-label>
<mat-form-field>
<textarea matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required></textarea>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status" >สถานะ</mat-slide-toggle>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit" >บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,73 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import {API, EAction, EText} from "../../../../@config/app";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
@Component({
selector: 'app-master-product-unit-do',
templateUrl: './master-product-unit-do.component.html',
styleUrls: []
})
export class MasterProductUnitDoComponent extends BasePopupComponent implements OnInit {
title = 'หน่วยนับ';
apiUrl: string = API.masterProductUnit;
constructor(
public dialogRef: MatDialogRef<MasterProductUnitDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {lastValueFrom} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {MasterProductUnitDoComponent} from "../do/master-product-unit-do.component";
@Component({
selector: 'app-master-product-unit-index',
templateUrl: './master-product-unit.component.html',
styleUrls: []
})
export class MasterProductUnitComponent extends BaseListComponent implements OnInit {
pageTitle = 'หน่วยนับ';
apiUrl: string = API.masterProductUnit;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(MasterProductUnitDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MasterProductUnitComponent } from './index/master-product-unit.component';
import {MasterProductUnitDoComponent} from "./do/master-product-unit-do.component";
const routes: Routes = [
{path: '', component: MasterProductUnitComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterProductUnitRoutingModule { }
export const RoutingComponents = [
MasterProductUnitComponent,
MasterProductUnitDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, MasterProductUnitRoutingModule} from './master-product-unit-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
MasterProductUnitRoutingModule
],
})
export class MasterProductUnitModule {}

View File

@@ -0,0 +1,38 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>ชื่อกล่องเก็บสินค้า</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-6 md:hidden"></div>
<div class="col-span-6 md:col-span-12">
<mat-label>ขนาดกล่อง (ลูกบาศก์)</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.size" name="size" #size="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, size)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-6 md:hidden"></div>
<div class="col-span-2 md:col-span-12">
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status" >สถานะ</mat-slide-toggle>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit" >บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,73 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import {API, EAction, EText} from "../../../../@config/app";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
@Component({
selector: 'app-master-storage-box-do',
templateUrl: './master-storage-box-do.component.html',
styleUrls: []
})
export class MasterStorageBoxDoComponent extends BasePopupComponent implements OnInit {
title = 'กล่องเก็บสินค้า';
apiUrl: string = API.masterStorageBox;
constructor(
public dialogRef: MatDialogRef<MasterStorageBoxDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
}

View File

@@ -0,0 +1,49 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tac">ชื่อกล่อง</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">{{item.name}}</td>
</ng-container>
<ng-container matColumnDef="size">
<th mat-header-cell *matHeaderCellDef class="tal">ขนาดกล่อง (ลูกบาศก์)</th>
<td mat-cell *matCellDef="let item" class="">{{item.size }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {lastValueFrom} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {MasterStorageBoxDoComponent} from "../do/master-storage-box-do.component";
@Component({
selector: 'app-master-storage-box-index',
templateUrl: './master-storage-box-index.component.html',
styleUrls: []
})
export class MasterStorageBoxIndexComponent extends BaseListComponent implements OnInit {
pageTitle = 'กล่องเก็บสินค้า';
apiUrl: string = API.masterStorageBox;
displayedColumns: string[] = ['action', 'name', 'size', 'status'];
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(MasterStorageBoxDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MasterStorageBoxIndexComponent } from './index/master-storage-box-index.component';
import {MasterStorageBoxDoComponent} from "./do/master-storage-box-do.component";
const routes: Routes = [
{path: '', component: MasterStorageBoxIndexComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MasterStorageBoxRoutingModule { }
export const RoutingComponents = [
MasterStorageBoxIndexComponent,
MasterStorageBoxDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, MasterStorageBoxRoutingModule} from './master-storage-box-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
MasterStorageBoxRoutingModule
],
})
export class MasterStorageBoxModule {}

View File

@@ -0,0 +1,120 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="card card-form-panel ">
<div class="card-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-12">
<div style="height: 25px;"></div>
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status">เปิดใช้งาน</mat-slide-toggle>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="">กำหนด packet</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm.packetDetail; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-2 md:col-span-4">
<label *ngIf="i === 0">รหัส</label>
<mat-form-field>
<input matInput name="code-{{i}}" #code="ngModel" [(ngModel)]="item.code" required disabled>
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-8">
<label *ngIf="i === 0">รายการจัดผ่อน</label>
<mat-form-field>
<input appNumberOnly matInput name="name-{{i}}" #name="ngModel" [(ngModel)]="item.name" disabled>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">จำนวน</label>
<mat-form-field>
<input appNumberOnly matInput name="value-{{i}}" #value="ngModel" [(ngModel)]="item.value" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">หน่วยนับ</label>
<ng-select placeholder="เลือกหน่วยนับ" name="unitId-{{i}}" #unit="ngModel" [(ngModel)]="item.unit" appendTo="body" required>
<ng-option *ngFor="let item of settingInstallmentUnit" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="">เลือกโปรโมชั่น</div>
</div>
<div class="card-body">
<ng-select placeholder="เลือกโปรโมชั่น" name="promotionId" #promotionId="ngModel" [(ngModel)]="dataForm.promotionId" (ngModelChange)="onChangePromotion($event)" appendTo="body">
<ng-option *ngFor="let item of promotionData" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
<ng-container *ngIf="promotionDetail">
<ng-container *ngFor="let item of promotionDetail; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-2 md:col-span-2 text-right">
<div *ngIf="i === 0" style="height: 25px;"></div>
<input type="checkbox" name="promotionStatus-{{i}}" #promotionStatus="ngModel" [(ngModel)]="item.status" disabled>
</div>
<div class="col-span-4 md:col-span-10 " >
<div *ngIf="i === 0" style="height: 25px;"></div>
<mat-form-field>
<input appNumberOnly matInput name="promotionName-{{i}}" #promotionName="ngModel" [(ngModel)]="item.name" disabled>
</mat-form-field>
</div>
<!-- <div class="col-span-2 md:col-span-6">-->
<!-- <label *ngIf="i === 0">จำนวน</label>-->
<!-- <mat-form-field>-->
<!-- <input appNumberOnly matInput name="promotionValue-{{i}}" #promotionValue="ngModel" [(ngModel)]="item.value" disabled >-->
<!-- </mat-form-field>-->
<!-- </div>-->
<!-- <div class="col-span-2 md:col-span-6">-->
<!-- <label *ngIf="i === 0">หน่วยนับ</label>-->
<!-- <ng-select placeholder="เลือกหน่วยนับ" name="promotionUnitId-{{i}}" #promotionUnit="ngModel" [(ngModel)]="item.unit" appendTo="body" disabled>-->
<!-- <ng-option *ngFor="let item of unitData" [value]="item">{{item}}</ng-option>-->
<!-- </ng-select>-->
<!-- </div>-->
</div>
</div>
</ng-container>
</ng-container>
<div style="height: 20px;"></div>
</div>
</div>
<div class="main-form-action text-right">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" class="btn btn-back" (click)="onAction('back')">ยกเลิก</button>
</div>
</form>

View File

@@ -0,0 +1,120 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { API, EAction, EText, PREFIX } from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { lastValueFrom } from "rxjs";
import { IProductMeasurement } from "../../../../app.interface";
import { ActivatedRoute, Router } from "@angular/router";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
@Component({
selector: "app-packet-do",
templateUrl: "./packet-do.component.html",
styleUrls: []
})
export class PacketDoComponent extends BaseFormComponent implements OnInit {
title = "จัดผ่อน";
api: any = API;
addItemNumber: number = 1;
masterProductUnit: any = [];
settingInstallmentUnit: any = ["บาท", "%"];
promotionData: any = [];
promotionDetail: any = [];
unitData: any = ["%"];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.activatedRoute.params.subscribe(async params => {
this.ids = params["id"];
this.action = params["action"];
this.promotionData = await lastValueFrom(this.appService.get(`${this.api.promotion}?showAll=true&status=true`));
if (!this.ids) this.dataForm.packetDetail = await lastValueFrom(this.appService.get(`${this.api.settings}?showAll=true&status=true&orderBy=code&sort=asc&codeIn=IN01,IN02,IN03,IN04,IN05`));
if (this.ids) await this.getData();
});
}
async onAction(action: string) {
if (action === "back") return this.router.navigate(["/pages/setting/packet"]);
return;
}
async onChangePromotion(value: any) {
if (!value) {
this.promotionDetail = [];
return;
}
const promotionDetail = this.promotionData.find((f: any) => f.id === value)?.promotionDetail;
this.promotionDetail = promotionDetail ? promotionDetail : [];
}
async getData() {
if (!this.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.packet}/getById/${this.ids}`));
this.promotionDetail = this.dataForm.promotion?.promotionDetail ? this.dataForm.promotion?.promotionDetail : [];
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
if (this.action === EAction.CREATE) return await this.onCreate();
if (this.action === EAction.UPDATE) return await this.onUpdate();
return;
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.api.packet, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.onAction("back");
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.api.packet}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.onAction("back");
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onAddItem(form: any) {
if (!form.valid) return false;
for (let i = 0; i < this.addItemNumber; i++) {
this.dataForm.productMeasurement?.push(<IProductMeasurement>{});
}
return;
}
onRemoveItem(i: number) {
console.log(this.dataForm.productMeasurement?.[i]);
this.dataForm.productMeasurement?.splice(i, 1);
this.changeDetectorRef.detectChanges();
}
protected readonly PREFIX = PREFIX;
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onAction()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BaseListComponent } from "../../../../@common/base/base-list.component";
import { lastValueFrom } from "rxjs";
import { AppService } from "../../../../app.service";
import { API, EAction, EText } from "../../../../@config/app";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-packet-index",
templateUrl: "./packet.component.html",
styleUrls: []
})
export class PacketComponent extends BaseListComponent implements OnInit {
pageTitle = "จัดผ่อน";
apiUrl: string = API.packet;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public appService: AppService
) {
super();
}
async ngOnInit() {
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(["/pages/setting/packet/do", "update", id]);
return this.router.navigate(["/pages/setting/packet/do", "create"]);
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,22 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {PacketComponent} from './index/packet.component';
import {PacketDoComponent} from "./do/packet-do.component";
const routes: Routes = [
{path: '', component: PacketComponent},
{path: 'do/:action', component: PacketDoComponent},
{path: 'do/:action/:id', component: PacketDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PacketRoutingModule {
}
export const RoutingComponents = [
PacketComponent,
PacketDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, PacketRoutingModule} from './packet-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
PacketRoutingModule
],
})
export class PacketModule {}

View File

@@ -0,0 +1,238 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-8 md:col-span-12">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-4 md:col-span-4">
<mat-label>BOM</mat-label>
<mat-form-field>
<input matInput name="code" #code="ngModel" [(ngModel)]="dataForm.code">
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12">
<mat-label>Brand</mat-label>
<ng-select placeholder="Choose Brand" name="brandId" #brandId="ngModel" [(ngModel)]="dataForm.brandId" appendTo="body" >
<ng-option *ngFor="let item of masterProductBrand" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>Model</mat-label>
<mat-form-field>
<input matInput name="name" #name="ngModel" [(ngModel)]="dataForm.name" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Main</mat-label>
<mat-form-field>
<input matInput name="size" #size="ngModel" [(ngModel)]="dataForm.size" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>น้ำหนัก</mat-label>
<mat-form-field>
<input matInput name="weight" #weight="ngModel" [(ngModel)]="dataForm.weight" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Color</mat-label>
<mat-form-field>
<input matInput name="color" #color="ngModel" [(ngModel)]="dataForm.color" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Year</mat-label>
<mat-form-field>
<input appNumberOnly matInput name="year" #year="ngModel" [(ngModel)]="dataForm.year" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Condition</mat-label>
<ng-select placeholder="Condition" name="condition" #condition="ngModel" [(ngModel)]="dataForm.condition" >
<ng-option *ngFor="let item of conditions" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Hardware</mat-label>
<mat-form-field>
<input matInput name="model" #model="ngModel" [(ngModel)]="dataForm.model" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Material</mat-label>
<mat-form-field>
<input matInput name="material" #material="ngModel" [(ngModel)]="dataForm.material" >
</mat-form-field>
</div>
<div class="col-span-3 md:col-span-12 ">
<mat-label>Index</mat-label>
<mat-form-field>
<input matInput name="index" #index="ngModel" [(ngModel)]="dataForm.index" >
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-12 ">
<mat-label>ราคา</mat-label>
<mat-form-field>
<input class="!text-right" matInput appCurrencyInputMask name="price" #price="ngModel" [(ngModel)]="dataForm.price" required>
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-12 ">
<mat-label>ราคาล่าสุด</mat-label>
<mat-form-field>
<input class="!text-right" matInput appCurrencyInputMask name="latestPrice" #latestPrice="ngModel" [(ngModel)]="dataForm.latestPrice" required>
</mat-form-field>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-6 md:col-span-12">
<div class="flex items-center w-full">
<div class="">รูปแบบการวัด</div>
<div class="ml-4">
<ng-select placeholder="เลือกรูปแบบการวัด" name="measurement" #measurement="ngModel" [(ngModel)]="addSelectMeasurement"
appendTo="body" (change)="onSelectMeasurement($event)">
<ng-option *ngFor="let item of masterProductMeasurement" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="col-span-6 md:col-span-12 ">
<form class="mt-2" #ngf2="ngForm" (ngSubmit)="onAddItem(ngf2)">
<div class="form-list-action flex items-center justify-end md:justify-start w-full">
<div class=""> ระบุจำนวนการวัด (จุด)</div>
<div class="ml-2 mr-2">
<mat-form-field>
<input matInput appNumberOnly name="addItemNum" #addItemNum="ngModel" [(ngModel)]="addItemNumber" >
</mat-form-field>
</div>
<div class="">
<button type="submit" class="btn btn-primary"> เพิ่ม</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm.productMeasurement; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-7 md:col-span-11">
<label *ngIf="i === 0">รายการวัด</label>
<mat-form-field>
<input matInput name="productMeasurementName-{{i}}" #productMeasurementName="ngModel" [(ngModel)]="item.name" >
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">ขนาด</label>
<mat-form-field>
<input appNumberOnly matInput name="productMeasurementSize-{{i}}" #productMeasurementSize="ngModel" [(ngModel)]="item.size" >
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-5">
<label *ngIf="i === 0">หน่วยนับ</label>
<ng-select placeholder="เลือกหน่วยนับ" name="productMeasurementUnit-{{i}}" #productMeasurementUnit="ngModel" [(ngModel)]="item.unitId" appendTo="body" >
<ng-option *ngFor="let item of masterProductUnit" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
<div class="col-span-1 md:col-span-1 text-center">
<div *ngIf="i === 0" style="height: 25px;"></div>
<i *ngIf="i !== 0" (click)="onRemoveItem(i)" class="bi bi-x-circle color-red cursor-pointer select-none"></i>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="mt-6">
<mat-form-field>
<textarea matInput [(ngModel)]="dataForm.desc" name="desc" #desc="ngModel" placeholder="รายละเอียดสินค้า"></textarea>
</mat-form-field>
</div>
</div>
<div class="col-span-4 md:col-span-12">
<div class="card card-form-panel">
<div class="card-header ">
<div class="card-title"> แกลลอรี่สินค้า</div>
</div>
<div class="card-body">
<div class="list-images">
<div class=" grid grid-cols-12 gap-2 md:gap-2 items-center">
<ng-container *ngFor="let item of attachments; let i = index">
<div class="col-span-4">
<div class="flex justify-center items-center list-images-item">
<div class="list-images-action">
<i *ngIf="dataForm.coverImage !== item" (click)="dataForm.coverImage = item"
matTooltip="ใช้เป็นรูปภาพหลัก" class="bi bi-star color-main cursor-pointer select-none"></i>
<i *ngIf="dataForm.coverImage === item" class="bi bi bi-star-fill color-main cursor-pointer select-none"></i>
<i (click)="onRemoveAttachments(i, item)" class="bi bi-x-circle color-red cursor-pointer select-none"></i>
</div>
<img src="{{storage.products}}/{{item}}" alt="">
</div>
</div>
</ng-container>
</div>
</div>
<div class="mb-2 mt-2">
<input hidden type="file" accept="image/*" #productImages (change)="onAttachments($event, 'products')" />
<button type="button" class="btn btn-sm btn-success-o" (click)="productImages.click()">เพิ่มคลังภาพสำหรับสินค้า</button>
</div>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="card-title"> หมวดหมู่สินค้า</div>
</div>
<div class="card-body">
<div class="category-panel">
<ng-container *ngFor="let item of masterProductCategory; let i = index">
<div class="item">
<label class="inline-flex items-center cursor-pointer select-none">
<input type="checkbox" name="checked-{{i}}" [(ngModel)]="item.checked">
<span class="ml-2">{{item.name}}</span>
</label>
</div>
</ng-container>
</div>
<div class="mt-2 pt-2 pb-2">
<a class="color-green cursor-pointer underline select-none fz-13" (click)="isCreateCategory = !isCreateCategory"> เพิ่มหมวดหมู่ใหม่ </a>
<ng-container *ngIf="isCreateCategory">
<form class="mt-2" #ngf3="ngForm" (ngSubmit)="onCreateCategory(ngf3)">
<mat-form-field class="mb-2">
<input placeholder="รหัสหมวดหมู่" matInput name="categoryCode" #categoryCode="ngModel" [(ngModel)]="dataCategoryForm.code" required>
</mat-form-field>
<mat-form-field>
<input placeholder="ชื่อหมวดหมู่" matInput name="categoryName" #categoryName="ngModel" [(ngModel)]="dataCategoryForm.name" required>
</mat-form-field>
<div class="mt-3">
<button type="submit" class="btn btn-sm btn-success-o">เพิ่มหมวดหมู่</button>
</div>
</form>
</ng-container>
</div>
</div>
</div>
</div>
</div>
<div class="main-form-action text-right">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" class="btn btn-back" (click)="onAction('back')">ยกเลิก</button>
</div>
</form>

View File

@@ -0,0 +1,218 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import {API, CONDITIONS, EAction, EText, STORAGE} from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { lastValueFrom } from "rxjs";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
import { ActivatedRoute, Router } from "@angular/router";
import { IProduct, IProductMeasurement } from "../../../../app.interface";
@Component({
selector: "app-products-do",
templateUrl: "./products-do.component.html",
styleUrls: []
})
export class ProductsDoComponent extends BaseFormComponent implements OnInit {
override dataForm: IProduct = {};
title = "";
api: any = API;
storage: any = STORAGE;
addItemNumber: number = 1;
addSelectMeasurement: any = null;
masterProductCategory: any = [];
masterProductBrand: any = [];
masterProductUnit: any = [];
masterProductMeasurement: any = [];
dataCategoryForm: any = {};
isCreateCategory: boolean = false;
attachments: any = [];
conditions = CONDITIONS;
// attachments: any = [
// "a92cbf24-7627-45c6-a007-e2e91ef023ac.png",
// "2400c71a-1dcb-4dad-8596-ad64e48bb6ee.png",
// "2400c71a-1dcb-4dad-8596-ad64e48bb6ee.png",
// "2400c71a-1dcb-4dad-8596-ad64e48bb6ee.png"
// ];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.activatedRoute.params.subscribe(async params => {
this.ids = params["id"];
this.action = params["action"];
this.masterProductCategory = await lastValueFrom(this.appService.get(`${this.api.masterProductCategory}?showAll=true&status=true&orderBy=name&sort=asc`));
this.masterProductBrand = await lastValueFrom(this.appService.get(`${this.api.masterProductBrand}?showAll=true&status=true&orderBy=name&sort=asc`));
this.masterProductUnit = await lastValueFrom(this.appService.get(`${this.api.masterProductUnit}?showAll=true&status=true&orderBy=name&sort=asc`));
this.masterProductMeasurement = await lastValueFrom(this.appService.get(`${this.api.masterProductMeasurement}?showAll=true&status=true&orderBy=name&sort=asc`));
if (!this.dataForm.productMeasurement?.[0]) {
this.dataForm.productMeasurement = [
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{},
<IProductMeasurement>{}
];
}
if (this.ids) await this.getData();
});
}
async onAction(action: string) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.BACK));
if (!sweetalert.isConfirmed) return;
if (action === "back") return this.router.navigate(["/pages/setting/products"]);
return;
}
async getData() {
if (!this.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.products}/getById/${this.ids}`));
this.masterProductCategory.map((item: any, i : number) => {
const checked = this.dataForm.productCategory?.find(f => f.categoryId === item.id);
item.checked = !!checked;
});
this.attachments = this.dataForm.images ? this.dataForm.images?.split(',') : [];
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
const masterProductCategory: any = [];
this.masterProductCategory.map((item: any) => {
if (item.checked) masterProductCategory.push(item.id);
});
this.dataForm.category = masterProductCategory?.[0] ? masterProductCategory.join(",") : null;
this.dataForm.images = this.attachments?.[0] ? this.attachments.join(",") : null;
if (this.action === EAction.CREATE) return await this.onCreate();
if (this.action === EAction.UPDATE) return await this.onUpdate();
return;
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.api.products, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.router.navigate(["/pages/setting/products"]);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.api.products}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.router.navigate(["/pages/setting/products"]);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onCreateCategory(form: any) {
if (!form.valid) return false;
try {
this.dataCategoryForm.status = true;
const res = await lastValueFrom(this.appService.post(this.api.masterProductCategory, this.dataCategoryForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
this.masterProductCategory.push(res);
this.dataCategoryForm = {};
this.isCreateCategory = false;
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
return;
}
async onSelectMeasurement($event : any) {
try {
const masterProductMeasurement = await lastValueFrom(this.appService.get(`${this.api.masterProductMeasurement}/getById/${$event}`));
this.dataForm.productMeasurement = [];
masterProductMeasurement.productMeasurement.map((item : any) => {
const data: any = {
name : item.name,
size : item.size,
unitId : item.unitId,
}
this.dataForm.productMeasurement?.push(data);
})
} catch (err) {
}
console.log($event);
}
onAddItem(form: any) {
if (!form.valid) return false;
for (let i = 0; i < this.addItemNumber; i++) {
this.dataForm.productMeasurement?.push(<IProductMeasurement>{});
}
return;
}
onRemoveItem(i: number) {
console.log(this.dataForm.productMeasurement?.[i]);
this.dataForm.productMeasurement?.splice(i, 1);
this.changeDetectorRef.detectChanges();
}
async onAttachments($event: any, type: any) {
const file = $event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append("ref", type);
formData.append("file", file);
try {
const res = await lastValueFrom(this.appService.post(`${this.api.attachments}/products`, formData));
if (!this.attachments[0]) {
this.dataForm.coverImage = res.fileName;
}
this.attachments.push(res.fileName);
console.log(this.attachments, res);
this.changeDetectorRef.detectChanges();
} catch (e) {
this.appService.message(EText.ERROR);
}
}
async onRemoveAttachments(i: number, fileName : string) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
// await lastValueFrom(this.appService.delete(`${this.api.attachments}/deleteByName`, fileName));
this.attachments?.splice(i, 1);
if (!this.attachments[0]) {
this.dataForm.coverImage = null;
}
this.changeDetectorRef.detectChanges();
}
}

View File

@@ -0,0 +1,37 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body !pb-0" >
<div style="height: 20px;"></div>
<div class="upload-wrap" (click)="files.click()">
<div class="">อัปโหลด Excel....</div>
<input
hidden
type="file"
accept="application/vnd.ms-excel,.xls,.xlsx,.csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xls,.xlsx,.csv,application/vnd.openxmlformats-officedocument.spreadsheetml.template,.xls,.xlsx,.csv,text/csv,.xls,.xlsx,.csv"
#files (change)="onImport($event)" />
</div>
<div class="upload-detail">
<ng-container *ngIf="dataFile?.name">
<div class="upload-detail-item">
<i class="bi bi-filetype-xlsx"></i> {{dataFile?.name}}
</div>
</ng-container>
</div>
<!-- <div class="upload-template">-->
<!-- <a (click)="onDownloadTemplate()"> ดาวน์โหลด Template สำหรับนำเข้ารายการสินค้า</a>-->
<!-- </div>-->
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit">นำเข้าข้อมูล</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,72 @@
import { ChangeDetectorRef, Component, Inject, OnInit } from "@angular/core";
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
import { BasePopupComponent } from "../../../../@common/base/base-popup.component";
import { API, EAction, EText } from "../../../../@config/app";
import { IDialogConfigData } from "../../../../@common/interface/Dialog";
import { AppService } from "../../../../app.service";
import { lastValueFrom } from "rxjs";
import { Router } from "@angular/router";
@Component({
selector: "app-product-import",
templateUrl: "./product-import.component.html",
styleUrls: []
})
export class ProductImportComponent extends BasePopupComponent implements OnInit {
title = "นำเข้าสินค้า";
api = API;
dataFile: any;
constructor(
public dialogRef: MatDialogRef<ProductImportComponent>,
@Inject(MAT_DIALOG_DATA) public dialog: IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
public router: Router,
) {
super();
}
async ngOnInit() {
}
async onImport($event: any) {
const file = $event.target.files[0];
if (!file) return;
try {
this.dataFile = file;
this.changeDetectorRef.detectChanges();
} catch (e) {
this.appService.message(EText.ERROR);
}
}
onDownloadTemplate() {
const url = `${this.api.url}/template/products-template.xlsx`;
window.open(url);
}
async onSubmit(form: any) {
if (!this.dataFile) return this.appService.message('กรุณาอัปโหลด Excel');
try {
const formData = new FormData();
formData.append("file", this.dataFile);
await lastValueFrom(this.appService.post(`${this.api.products}/import`, formData));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
this.dialogRef.close(EAction.GET);
} catch (e) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,127 @@
<div class="card card-table">
<div class="card-filter text-right">
<div class="card-filter-section grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-5 md:col-span-12 md:order-2">
<mat-form-field>
<i matTextPrefix class="bi bi-search"></i>
<input matInput name="keyword" #keyword="ngModel" [(ngModel)]="dataFilter.keyword" (ngModelChange)="onFilter($event)">
</mat-form-field>
</div>
<div class="col-span-7 md:col-span-12 md:order-1">
<div class="card-header-action">
<button type="button" class="btn btn-export" (click)="onExport()">Export</button>
<button type="button" class="btn btn-import" (click)="onImport()">Import</button>
<button type="button" class="btn btn-create" (click)="onAction()">
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
</div>
</div>
<div class="card-filter-section grid grid-cols-12 gap-4 items-center md:gap-2 ">
<div class="col-span-3 md:col-span-6">
<ng-select name="categoryId" #categoryId="ngModel" [(ngModel)]="dataFilter.categoryId" (ngModelChange)="getData()" appendTo="body" required placeholder="เลือกหมวดหมู่">
<ng-option *ngFor="let item of masterProductCategory" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
<div class="col-span-3 md:col-span-6">
<ng-select placeholder="Choose Brand" name="brandId" #brandId="ngModel" [(ngModel)]="dataFilter.brandId" (ngModelChange)="getData()" appendTo="body" required>
<ng-option *ngFor="let item of masterProductBrand" [value]="item.id">{{item.name}}</ng-option>
</ng-select>
</div>
<div class="col-span-6 md:col-span-12 ">
<div class="flex w-full justify-end md:justify-start">
<div class="">จำนวนทั้งหมด {{totalItem}} รายการ</div>
<div class="pl-2 pr-2">|</div>
<div class="">ค้นหาจำนวน {{totalOfElement}} รายการ</div>
</div>
</div>
</div>
</div>
<div class="card-body">
<div class="table-wrap">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)">
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac" mat-sort-header>BOM</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">{{item.code}}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">Model</th>
<td mat-cell *matCellDef="let item" class="" style="min-width: 200px;">
<!-- <div class="flex items-center">-->
<!-- <div class="image-td"><img *ngIf="item.coverImage" src="{{storage.products}}/{{item.coverImage}}" alt=""></div>-->
<!-- <div class="">{{item.name }}</div>-->
<!-- </div>-->
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="brandId">
<th mat-header-cell *matHeaderCellDef class="tal" mat-sort-header>Brand</th>
<td mat-cell *matCellDef="let item" class="">{{item?.masterProductBrand?.name }}</td>
</ng-container>
<ng-container matColumnDef="size">
<th mat-header-cell *matHeaderCellDef class="tal" width="150">Main</th>
<td mat-cell *matCellDef="let item" class="">{{item.size }}</td>
</ng-container>
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef class="tal" width="150">น้ำหนัก</th>
<td mat-cell *matCellDef="let item" class="">{{item.weight }}</td>
</ng-container>
<ng-container matColumnDef="color">
<th mat-header-cell *matHeaderCellDef class="tal" width="150">Color</th>
<td mat-cell *matCellDef="let item" class="">{{item.color }}</td>
</ng-container>
<ng-container matColumnDef="year">
<th mat-header-cell *matHeaderCellDef class="tal" width="150">Year</th>
<td mat-cell *matCellDef="let item" class="">{{item.year }}</td>
</ng-container>
<ng-container matColumnDef="price">
<th mat-header-cell *matHeaderCellDef class="tal" width="150" mat-sort-header>ราคา</th>
<td mat-cell *matCellDef="let item" class="">
<div class="b-color-orange"> {{item.price | number : '1.2-2'}}</div>
</td>
</ng-container>
<ng-container matColumnDef="latestPrice">
<th mat-header-cell *matHeaderCellDef class="tal" width="150" mat-sort-header>ราคาล่าสุด</th>
<td mat-cell *matCellDef="let item" class="">
<div class="b-color-green"> {{item.latestPrice | number : '1.2-2' }}</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="80">Action</th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-stickies-fill color-green" (click)="onCopy(item.id)"></i>
</div>
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
</div>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,139 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import { debounceTime, distinctUntilChanged, lastValueFrom, Subject } from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {ProductsDoComponent} from "../do/products-do.component";
import {Router} from "@angular/router";
import { generateUUID } from "../../../../@common/utils/generateUUID";
import generateParamsValue from "../../../../@common/utils/GenerateParamsValue";
import deepCopy from "../../../../@common/utils/DeepCopy";
import { ProductImportComponent } from "../import/product-import.component";
@Component({
selector: 'app-products-index',
templateUrl: './products.component.html',
styleUrls: []
})
export class ProductsComponent extends BaseListComponent implements OnInit {
pageTitle = 'สินค้า';
apiUrl: string = API.products;
api: any = API;
displayedColumns: string[] = ['action','price','latestPrice', 'code','name','brandId','size','weight','color','year'];
masterProductCategory : any = []
masterProductBrand : any = []
filterKeyword: Subject<string> = new Subject<string>();
constructor(
private dialog: MatDialog,
private router: Router,
public appService: AppService,
) {
super();
this.filterKeyword.pipe(debounceTime(1000), distinctUntilChanged()).subscribe(model => {
this.getData();
});
}
async ngOnInit() {
this.masterProductCategory = await lastValueFrom(this.appService.get(`${this.api.masterProductCategory}?showAll=true&status=true`));
this.masterProductBrand = await lastValueFrom(this.appService.get(`${this.api.masterProductBrand}?showAll=true&status=true`));
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(['/pages/setting/products/do', 'update', id]);
return this.router.navigate(['/pages/setting/products/do', 'create']);
}
async getData($event?: any) {
try {
this.dataFilter.keywordColumn = 'code,name,price,latestPrice,size,color,year';
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
} catch (e) {
this.dataSource = [];
}
}
onFilter($event? : any) {
this.filterKeyword.next($event);
}
async onSort($event: any) {
this.dataFilter.orderBy = $event.active;
this.dataFilter.sort = $event.direction;
await this.getData();
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(ProductsDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onCopy(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.COPY));
if (!sweetalert.isConfirmed) return;
try {
const product = await lastValueFrom(this.appService.get(`${this.api.products}/getById/${ids}`));
delete product.id;
product.name = `${product.name} (copy)`;
product.productMeasurement.map((item : any) => {
delete item.id;
})
const masterProductCategory: any[] = [];
product.productCategory.map((item : any) => {
masterProductCategory.push(item.categoryId);
});
product.category = masterProductCategory?.[0] ? masterProductCategory.join(",") : null;
delete product.productCategory;
await lastValueFrom(this.appService.post(this.api.products, product));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onExport() {
const filter = generateParamsValue(this.dataFilter);
const url = `${this.api.url}/products/export?${filter ? '&' + filter : '' }`;
window.open(url);
}
async onImport() {
const dialogConfig = deepCopy(this.dialogConfig);
dialogConfig.width = '50%';
dialogConfig.height = '50%';
dialogConfig.data.action = EAction.POPUP;
const dialogRef = this.dialog.open(ProductImportComponent, dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
}

View File

@@ -0,0 +1,24 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {ProductsComponent} from './index/products.component';
import {ProductsDoComponent} from "./do/products-do.component";
import { ProductImportComponent } from "./import/product-import.component";
const routes: Routes = [
{path: '', component: ProductsComponent},
{path: 'do/:action', component: ProductsDoComponent},
{path: 'do/:action/:id', component: ProductsDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ProductsRoutingModule {
}
export const RoutingComponents = [
ProductsComponent,
ProductsDoComponent,
ProductImportComponent,
];

View File

@@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, ProductsRoutingModule} from './products-routing.module';
import {AppSharedModule} from "../../../app.shared";
import { NgOptimizedImage } from "@angular/common";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
ProductsRoutingModule,
NgOptimizedImage
]
})
export class ProductsModule {}

View File

@@ -0,0 +1,84 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="card card-form-panel ">
<div class="card-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
<div class="col-span-6 md:col-span-12">
<mat-label>รหัส</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.code" name="code" #code="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, code)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-12">
<div style="height: 25px;"></div>
<mat-slide-toggle [(ngModel)]="dataForm.status" name="status">เปิดใช้งาน</mat-slide-toggle>
</div>
<div class="col-span-12 md:col-span-12">
<mat-label>ชื่อ</mat-label>
<mat-form-field>
<input matInput [(ngModel)]="dataForm.name" name="name" #name="ngModel" required>
<mat-error *ngIf="isFieldValid(ngf, name)"> กรุณากรอกข้อมูล</mat-error>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12">
<mat-label>ประเภทโปรโมชั่น</mat-label>
<ng-select placeholder="เลือกประเภทโปรโมชั่น" name="type" #type="ngModel" [(ngModel)]="dataForm.type" appendTo="body" required>
<ng-option *ngFor="let item of promotionTypeData" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
</div>
<div style="height: 20px;"></div>
</div>
</div>
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="">จัดการโปรโมชั่น</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm.promotionDetail; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-2 md:col-span-2 text-right">
<div *ngIf="i === 0" style="height: 25px;"></div>
<input type="checkbox" name="status-{{i}}" #status="ngModel" [(ngModel)]="item.status">
</div>
<div class="col-span-4 md:col-span-10 " (click)="item.status = !item.status">
<div *ngIf="i === 0" style="height: 25px;"></div>
<mat-form-field>
<input appNumberOnly matInput class="cursor-pointer select-none" name="name-{{i}}" #name="ngModel" [(ngModel)]="item.name" disabled>
</mat-form-field>
</div>
<!-- <div class="col-span-2 md:col-span-6">-->
<!-- <label *ngIf="i === 0">จำนวน</label>-->
<!-- <mat-form-field>-->
<!-- <input appNumberOnly matInput name="value-{{i}}" #value="ngModel" [(ngModel)]="item.value" [required]="item.status">-->
<!-- </mat-form-field>-->
<!-- </div>-->
<!-- <div class="col-span-2 md:col-span-6">-->
<!-- <label *ngIf="i === 0">หน่วยนับ</label>-->
<!-- <ng-select placeholder="เลือกหน่วยนับ" name="unitId-{{i}}" #unit="ngModel" [(ngModel)]="item.unit" appendTo="body" disabled>-->
<!-- <ng-option *ngFor="let item of unitData" [value]="item">{{item}}</ng-option>-->
<!-- </ng-select>-->
<!-- </div>-->
</div>
</div>
</ng-container>
<div style="height: 20px;"></div>
</div>
</div>
<div class="main-form-action text-right">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" class="btn btn-back" (click)="onAction('back')">ยกเลิก</button>
</div>
</form>

View File

@@ -0,0 +1,125 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { API, EAction, EText, PREFIX } from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { lastValueFrom } from "rxjs";
import { IProductMeasurement } from "../../../../app.interface";
import { ActivatedRoute, Router } from "@angular/router";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
@Component({
selector: "app-promotion-do",
templateUrl: "./promotion-do.component.html",
styleUrls: []
})
export class PromotionDoComponent extends BaseFormComponent implements OnInit {
title = "โปรโมชั่น";
api: any = API;
addItemNumber: number = 1;
masterProductUnit: any = [];
unitData: any = ["%"];
promotionData: any = [];
promotionTypeData: any = ["งวด"];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.activatedRoute.params.subscribe(async params => {
this.ids = params["id"];
this.action = params["action"];
this.dataForm.type = "งวด";
this.defaultData();
if (this.ids) await this.getData();
});
}
defaultData() {
const promotionDetail: any[] = [];
for (let i = 0; i < 12; i++) {
const item : any = {
code : i + 1,
status : false,
name : `งวดที่ ${i + 1}`,
value : 0,
unit: '%'
}
promotionDetail.push(item)
}
this.dataForm.promotionDetail = promotionDetail;
}
async onAction(action: string) {
if (action === "back") return this.router.navigate(["/pages/setting/promotion"]);
return;
}
async getData() {
if (!this.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.promotion}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
if (this.action === EAction.CREATE) return await this.onCreate();
if (this.action === EAction.UPDATE) return await this.onUpdate();
return;
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.api.promotion, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.onAction("back");
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.api.promotion}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.onAction("back");
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onAddItem(form: any) {
if (!form.valid) return false;
for (let i = 0; i < this.addItemNumber; i++) {
this.dataForm.productMeasurement?.push(<IProductMeasurement>{});
}
return;
}
onRemoveItem(i: number) {
console.log(this.dataForm.productMeasurement?.[i]);
this.dataForm.productMeasurement?.splice(i, 1);
this.changeDetectorRef.detectChanges();
}
protected readonly PREFIX = PREFIX;
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onAction()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BaseListComponent } from "../../../../@common/base/base-list.component";
import { lastValueFrom } from "rxjs";
import { AppService } from "../../../../app.service";
import { API, EAction, EText } from "../../../../@config/app";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-promotion-index",
templateUrl: "./promotion.component.html",
styleUrls: []
})
export class PromotionComponent extends BaseListComponent implements OnInit {
pageTitle = "โปรโมชั่น";
apiUrl: string = API.promotion;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public appService: AppService
) {
super();
}
async ngOnInit() {
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(["/pages/setting/promotion/do", "update", id]);
return this.router.navigate(["/pages/setting/promotion/do", "create"]);
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,22 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {PromotionComponent} from './index/promotion.component';
import {PromotionDoComponent} from "./do/promotion-do.component";
const routes: Routes = [
{path: '', component: PromotionComponent},
{path: 'do/:action', component: PromotionDoComponent},
{path: 'do/:action/:id', component: PromotionDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PromotionRoutingModule {
}
export const RoutingComponents = [
PromotionComponent,
PromotionDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, PromotionRoutingModule} from './promotion-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
PromotionRoutingModule
],
})
export class PromotionModule {}

View File

@@ -0,0 +1,72 @@
<form class="dialog-main form-dialog " #ngf="ngForm" (ngSubmit)="onSubmit(ngf)" autocomplete="off">
<div class="dialog-main">
<div class="dialog-header">
<h2>{{title}}</h2>
</div>
<div class="dialog-body">
<div class="grid grid-cols-12 gap-4 md:gap-2 mt-4 mb-4">
<div class="col-span-4 md:col-span-12 ">
<mat-label>รหัสร้านค้า</mat-label>
<mat-form-field>
<input matInput name="code" #code="ngModel" [(ngModel)]="dataForm.code" required>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>ชื่อคนขาย/ร้านค้า</mat-label>
<mat-form-field>
<input matInput name="sellerName" #sellerName="ngModel" [(ngModel)]="dataForm.name" required>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>เบอร์โทร</mat-label>
<mat-form-field>
<input matInput name="sellerPhone" #sellerPhone="ngModel" [(ngModel)]="dataForm.phone" required>
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>Facebook</mat-label>
<mat-form-field>
<input matInput name="sellerFacebook" #sellerFacebook="ngModel" [(ngModel)]="dataForm.facebook" >
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>ID Line</mat-label>
<mat-form-field>
<input matInput name="sellerLine" #sellerLine="ngModel" [(ngModel)]="dataForm.line" >
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>ID LINE ร้านค้า</mat-label>
<mat-form-field>
<input matInput name="sellerLineShop" #sellerLineShop="ngModel" [(ngModel)]="dataForm.lineShop" >
</mat-form-field>
</div>
<div class="col-span-4 md:col-span-12 ">
<mat-label>IG</mat-label>
<mat-form-field>
<input matInput name="sellerIg" #sellerIg="ngModel" [(ngModel)]="dataForm.ig" >
</mat-form-field>
</div>
<!-- <div class="col-span-4 md:col-span-12 ">-->
<!-- <mat-label>S/N สินค้า</mat-label>-->
<!-- <mat-form-field>-->
<!-- <input matInput name="sellerSnProduct" #sellerSnProduct="ngModel" [(ngModel)]="dataForm.snProduct" >-->
<!-- </mat-form-field>-->
<!-- </div>-->
</div>
</div>
<div class="dialog-footer">
<button type="submit" class="btn btn-submit">บันทึก</button>
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,107 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
import { API, EAction, EText, GENDER, PREFIX } from "../../../../@config/app";
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {lastValueFrom} from "rxjs";
import {BasePopupComponent} from "../../../../@common/base/base-popup.component";
import {IDialogConfigData} from "../../../../@common/interface/Dialog";
import deepCopy from "../../../../@common/utils/DeepCopy";
import { AttachmentsViewComponent } from "../../../@popup/attachments-view/attachments-view.component";
@Component({
selector: 'app-customer-do',
templateUrl: './seller-do.component.html',
styleUrls: []
})
export class SellerDoComponent extends BasePopupComponent implements OnInit {
title = 'ร้านค้า';
apiUrl: string = API.seller;
constructor(
public dialogRef: MatDialogRef<SellerDoComponent>,
@Inject(MAT_DIALOG_DATA) public dialog : IDialogConfigData,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService,
private attachments: MatDialog,
) {
super();
}
async ngOnInit() {
if (this.dialog.action === EAction.UPDATE) await this.getData();
}
async getData() {
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
this.ids = this.dialog.ids;
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.apiUrl}/getById/${this.ids}`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close();
}
}
async onSubmit(form : any) {
if (!form.valid) return false;
if (this.dialog.action === EAction.CREATE) return await this.onCreate();
if (this.dialog.action === EAction.UPDATE) return await this.onUpdate();
}
async onCreate() {
try {
await lastValueFrom(this.appService.post(this.apiUrl, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.CREATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onUpdate() {
try {
await lastValueFrom(this.appService.post(`${this.apiUrl}/update/${this.ids}`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.dialogRef.close(EAction.GET);
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
this.dialogRef.close(EAction.GET);
}
}
async onAttachments($event: any, type: any) {
const file = $event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append("ref", type);
formData.append("file", file);
try {
const res = await lastValueFrom(this.appService.post(`${API.attachments}/images`, formData));
this.dataForm.idCardImage = res.fileName;
this.changeDetectorRef.detectChanges();
} catch (e) {
this.appService.message(EText.ERROR);
}
}
async onAttachmentsView(type : any) {
const dialogConfig = deepCopy(this.dialogConfig);
dialogConfig.data.action = EAction.POPUP;
dialogConfig.data.title = 'สำเนาบัตรประชาชน';
dialogConfig.data.type = type;
dialogConfig.data.images = this.dataForm.idCardImage;
const dialogRef = this.attachments.open(AttachmentsViewComponent, dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
}
}

View File

@@ -0,0 +1,90 @@
<div class="card card-table">
<div class="card-filter text-right">
<div class="card-filter-section grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-5 md:col-span-12 md:order-2">
<mat-form-field>
<i matTextPrefix class="bi bi-search"></i>
<input matInput name="keyword" #keyword="ngModel" [(ngModel)]="dataFilter.keyword" (ngModelChange)="onFilter($event)">
</mat-form-field>
</div>
<div class="col-span-7 md:col-span-12 md:order-1">
<div class="card-header-action">
<button type="button" class="btn btn-export" (click)="onExport()">Export</button>
<button type="button" class="btn btn-create" (click)="onPopup()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
</div>
</div>
</div>
<div class="card-body">
<div class="table-wrap">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tal">รหัสร้านค้า</th>
<td mat-cell *matCellDef="let item" style="min-width: 200px;"> {{item.code}}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อร้านค้า</th>
<td mat-cell *matCellDef="let item" style="min-width: 200px;"> {{item.name}}</td>
</ng-container>
<ng-container matColumnDef="phone">
<th mat-header-cell *matHeaderCellDef class="tal">เบอร์โทร</th>
<td mat-cell *matCellDef="let item" class="">{{item.phone }}</td>
</ng-container>
<ng-container matColumnDef="line">
<th mat-header-cell *matHeaderCellDef class="tal">ID Line</th>
<td mat-cell *matCellDef="let item" class="">{{item.line }}</td>
</ng-container>
<ng-container matColumnDef="lineShop">
<th mat-header-cell *matHeaderCellDef class="tal">Line Shop</th>
<td mat-cell *matCellDef="let item" class="">{{item.lineShop }}</td>
</ng-container>
<ng-container matColumnDef="ig">
<th mat-header-cell *matHeaderCellDef class="tal">Ig</th>
<td mat-cell *matCellDef="let item" class="">{{item.ig }}</td>
</ng-container>
<ng-container matColumnDef="facebook">
<th mat-header-cell *matHeaderCellDef class="tal">Facebook</th>
<td mat-cell *matCellDef="let item" class="">{{item.facebook }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onPopup(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
</div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,76 @@
import {Component, OnInit} from '@angular/core';
import {BaseListComponent} from "../../../../@common/base/base-list.component";
import {debounceTime, distinctUntilChanged, lastValueFrom, Subject} from "rxjs";
import {MatDialog} from "@angular/material/dialog";
import {AppService} from "../../../../app.service";
import {API, EAction, EText} from "../../../../@config/app";
import {SellerDoComponent} from "../do/seller-do.component";
import generateParamsValue from "../../../../@common/utils/GenerateParamsValue";
@Component({
selector: 'app-customer-index',
templateUrl: './seller-index.component.html',
styleUrls: []
})
export class SellerIndexComponent extends BaseListComponent implements OnInit {
pageTitle = 'ร้านค้า';
apiUrl: string = API.seller;
displayedColumns: string[] = ['action', 'code', 'name','phone','line','lineShop','facebook','ig'];
filterKeyword: Subject<string> = new Subject<string>();
constructor(
private dialog: MatDialog,
public appService: AppService,
) {
super();
this.filterKeyword.pipe(debounceTime(1000), distinctUntilChanged()).subscribe(model => {
this.getData();
});
}
async ngOnInit() {
await this.getData();
}
async getData($event?: any) {
this.dataFilter.keywordColumn = 'code,name,phone,line,lineShop,facebook,ig';
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter($event? : any) {
this.filterKeyword.next($event);
}
onSort($event: any) {
console.log($event);
}
async onPopup(ids?: any) {
this.dialogConfig.data.ids = ids;
this.dialogConfig.data.action = ids ? EAction.UPDATE : EAction.CREATE;
const dialogRef = this.dialog.open(SellerDoComponent, this.dialogConfig);
const afterClosed = await lastValueFrom(dialogRef.afterClosed());
if (afterClosed === EAction.GET) {
await this.getData(this.getCurrentPage());
}
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
onExport() {
const filter = generateParamsValue(this.dataFilter);
const url = `${API.seller}/export?${filter ? '&' + filter : '' }`;
window.open(url);
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SellerIndexComponent } from './index/seller-index.component';
import {SellerDoComponent} from "./do/seller-do.component";
const routes: Routes = [
{path: '', component: SellerIndexComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SellerRoutingModule { }
export const RoutingComponents = [
SellerIndexComponent,
SellerDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {RoutingComponents, SellerRoutingModule} from './seller-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...RoutingComponents,
],
imports: [
AppSharedModule,
SellerRoutingModule
],
})
export class SellerModule {}

View File

@@ -0,0 +1,31 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="">กำหนดค่า</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-4 md:col-span-6 !text-right">
<label style="text-align: right !important;"> {{item.name}}</label>
</div>
<div class="col-span-2 md:col-span-6">
<mat-form-field>
<input appNumberOnly matInput name="value-{{i}}" #value="ngModel" [(ngModel)]="item.value" required>
</mat-form-field>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="main-form-footer">
<button type="submit" class="btn btn-submit">บันทึก</button>
</div>
</form>

View File

@@ -0,0 +1,63 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { API, EAction, EText } from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { BasePopupComponent } from "../../../../@common/base/base-popup.component";
import { lastValueFrom } from "rxjs";
import { IProductMeasurement } from "../../../../app.interface";
import { ActivatedRoute, Router } from "@angular/router";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
@Component({
selector: "app-installment-do",
templateUrl: "./setting-deviation-do.component.html",
styleUrls: []
})
export class SettingDeviationDoComponent extends BaseFormComponent implements OnInit {
title = "ค่าเบี่ยงเบนการวัด";
api: any = API;
addItemNumber: number = 1;
settingInstallmentUnit: any = [];
override dataForm : any[] = [];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.settingInstallmentUnit = ['บาท', '%'];
await this.getData();
}
async getData() {
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.settings}?showAll=true&status=true&orderBy=code&sort=asc&codeIn=DEVIATION`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
try {
await lastValueFrom(this.appService.post(`${this.api.settings}/update-list`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.getData();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
return;
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onAction()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BaseListComponent } from "../../../../@common/base/base-list.component";
import { lastValueFrom } from "rxjs";
import { AppService } from "../../../../app.service";
import { API, EAction, EText } from "../../../../@config/app";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-setting-installment-index",
templateUrl: "./setting-deviation.component.html",
styleUrls: []
})
export class SettingDeviationComponent extends BaseListComponent implements OnInit {
pageTitle = "จัดผ่อน";
apiUrl: string = API.settings;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public appService: AppService
) {
super();
}
async ngOnInit() {
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(["/pages/setting/product-measurement/do", "update", id]);
return this.router.navigate(["/pages/setting/product-measurement/do", "create"]);
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,20 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {SettingDeviationComponent} from './index/setting-deviation.component';
import {SettingDeviationDoComponent} from "./do/setting-deviation-do.component";
const routes: Routes = [
{path: '', component: SettingDeviationDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SettingDeviationRoutingModule {
}
export const ProductRoutingComponents = [
SettingDeviationComponent,
SettingDeviationDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {ProductRoutingComponents, SettingDeviationRoutingModule} from './setting-deviation-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...ProductRoutingComponents,
],
imports: [
AppSharedModule,
SettingDeviationRoutingModule
],
})
export class SettingDeviationModule {}

View File

@@ -0,0 +1,46 @@
<form class="main-form" #ngf="ngForm" (ngSubmit)="onSubmit(ngf)">
<div class="card card-form-panel mt-6">
<div class="card-header ">
<div class="">กำหนดการคำนวนการจัดผ่อน</div>
</div>
<div class="card-body">
<ng-container *ngFor="let item of dataForm; let i = index">
<div class="form-list">
<div class="form-list-item grid grid-cols-12 gap-4 md:gap-2 items-center">
<div class="col-span-2 md:col-span-4">
<label *ngIf="i === 0">รหัส</label>
<mat-form-field>
<input matInput name="code-{{i}}" #code="ngModel" [(ngModel)]="item.code" required disabled>
</mat-form-field>
</div>
<div class="col-span-6 md:col-span-8">
<label *ngIf="i === 0">รายการจัดผ่อน</label>
<mat-form-field>
<input appNumberOnly matInput name="name-{{i}}" #name="ngModel" [(ngModel)]="item.name" disabled>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">จำนวน</label>
<mat-form-field>
<input appNumberOnly matInput name="value-{{i}}" #value="ngModel" [(ngModel)]="item.value" required>
</mat-form-field>
</div>
<div class="col-span-2 md:col-span-6">
<label *ngIf="i === 0">หน่วยนับ</label>
<ng-select placeholder="เลือกหน่วยนับ" name="unitId-{{i}}" #unit="ngModel" [(ngModel)]="item.unit" appendTo="body" required>
<ng-option *ngFor="let item of settingInstallmentUnit" [value]="item">{{item}}</ng-option>
</ng-select>
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div class="main-form-footer">
<button type="submit" class="btn btn-submit">บันทึก</button>
</div>
</form>

View File

@@ -0,0 +1,61 @@
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { API, EAction, EText } from "../../../../@config/app";
import { AppService } from "../../../../app.service";
import { BasePopupComponent } from "../../../../@common/base/base-popup.component";
import { lastValueFrom } from "rxjs";
import { IProductMeasurement } from "../../../../app.interface";
import { ActivatedRoute, Router } from "@angular/router";
import { BaseFormComponent } from "../../../../@common/base/base-form.component";
@Component({
selector: "app-installment-do",
templateUrl: "./setting-installment-do.component.html",
styleUrls: []
})
export class SettingInstallmentDoComponent extends BaseFormComponent implements OnInit {
title = "จัดผ่อน";
api: any = API;
addItemNumber: number = 1;
settingInstallmentUnit: any = [];
override dataForm : any[] = [];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public changeDetectorRef: ChangeDetectorRef,
public appService: AppService
) {
super();
}
async ngOnInit() {
this.settingInstallmentUnit = ['บาท', '%'];
await this.getData();
}
async getData() {
try {
this.dataForm = await lastValueFrom(this.appService.get(`${this.api.settings}?showAll=true&status=true&orderBy=code&sort=asc&codeIn=IN01,IN02,IN03,IN04,IN05`));
this.changeDetectorRef.detectChanges();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
async onSubmit(form: any) {
if (!form.valid) return false;
try {
await lastValueFrom(this.appService.post(`${this.api.settings}/update-list`, this.dataForm));
await this.appService.message(EAction.SUCCESS, EText.UPDATE);
await this.getData();
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
return;
}
}

View File

@@ -0,0 +1,53 @@
<div class="card card-table">
<div class="card-header text-right">
<button type="button" class="btn btn-create" (click)="onAction()" >
<i class="bi bi-plus"></i>
เพิ่ม{{pageTitle}}
</button>
</div>
<div class="card-body">
<table class="table table-main" mat-table [dataSource]="dataSource" matSort (matSortChange)="onSort($event)" >
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<ng-container matColumnDef="code">
<th mat-header-cell *matHeaderCellDef class="tac">รหัส</th>
<td mat-cell *matCellDef="let item" width="150" class="tac">
{{item.code}}
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อ{{pageTitle}}</th>
<td mat-cell *matCellDef="let item" class="">
{{item.name }}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="tac" width="100">สถานะ</th>
<td mat-cell *matCellDef="let item" class="tac">
<div *ngIf="item.status" class="status status-active">ใช้งาน</div>
<div *ngIf="!item.status" class="status status-disabled">ปิดใช้งาน</div>
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef width="100"> </th>
<td mat-cell *matCellDef="let item">
<div class="action flex justify-center">
<div class="item">
<i class="bi bi-pencil-square icon-edit" (click)="onAction(item.id)"></i>
</div>
<div class="item icon-delete">
<i class="bi bi-trash3" (click)="onDelete(item.id)"></i>
</div>
</div>
</td>
</ng-container>
</table>
<div *ngIf="dataSourceCount === 0" class="no-data"></div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons (page)="getData($event)"></mat-paginator>
</div>
</div>

View File

@@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BaseListComponent } from "../../../../@common/base/base-list.component";
import { lastValueFrom } from "rxjs";
import { AppService } from "../../../../app.service";
import { API, EAction, EText } from "../../../../@config/app";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-setting-installment-index",
templateUrl: "./setting-installment.component.html",
styleUrls: []
})
export class SettingInstallmentComponent extends BaseListComponent implements OnInit {
pageTitle = "จัดผ่อน";
apiUrl: string = API.settings;
displayedColumns: string[] = ['action', 'code', 'name', 'status'];
constructor(
public activatedRoute: ActivatedRoute,
public router: Router,
public appService: AppService
) {
super();
}
async ngOnInit() {
await this.getData();
}
onAction(id?: any) {
if (id) return this.router.navigate(["/pages/setting/product-measurement/do", "update", id]);
return this.router.navigate(["/pages/setting/product-measurement/do", "create"]);
}
async getData($event?: any) {
const dataSource = await lastValueFrom(this.appService.get(this.setParams(this.apiUrl, $event)));
this.dataSource = this.setDataSource<any>(dataSource);
}
onFilter() {
}
onSort($event: any) {
console.log($event);
}
async onDelete(ids: any) {
const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
if (!sweetalert.isConfirmed) return;
try {
await lastValueFrom(this.appService.delete(this.apiUrl, ids));
await this.appService.message(EAction.SUCCESS, EText.DELETE);
await this.getData(this.getCurrentPage());
} catch (err) {
this.appService.message(EAction.ERROR, EText.ERROR);
}
}
}

View File

@@ -0,0 +1,20 @@
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {SettingInstallmentComponent} from './index/setting-installment.component';
import {SettingInstallmentDoComponent} from "./do/setting-installment-do.component";
const routes: Routes = [
{path: '', component: SettingInstallmentDoComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SettingInstallmentRoutingModule {
}
export const ProductRoutingComponents = [
SettingInstallmentComponent,
SettingInstallmentDoComponent,
];

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import {ProductRoutingComponents, SettingInstallmentRoutingModule} from './setting-installment-routing.module';
import {AppSharedModule} from "../../../app.shared";
@NgModule({
declarations: [
...ProductRoutingComponents,
],
imports: [
AppSharedModule,
SettingInstallmentRoutingModule
],
})
export class SettingInstallmentModule {}