[update] settings menu
This commit is contained in:
@@ -55,4 +55,33 @@ export const MENU: MENU[] = [
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Setting',
|
||||
link: 'setting',
|
||||
permission: 'setting',
|
||||
icon: 'bi bi-gear-fill',
|
||||
params: [],
|
||||
badge: '',
|
||||
type: 'collapsable',
|
||||
children: [
|
||||
{
|
||||
name: 'Banner',
|
||||
link: 'setting/banner',
|
||||
permission: 'banner',
|
||||
type: 'link',
|
||||
icon: '',
|
||||
params: [],
|
||||
badge: '',
|
||||
},
|
||||
{
|
||||
name: 'Promotion',
|
||||
link: 'setting/promotion',
|
||||
permission: 'promotion',
|
||||
type: 'link',
|
||||
icon: '',
|
||||
params: [],
|
||||
badge: '',
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@@ -44,6 +44,19 @@ const routes: Routes = [
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
children: [
|
||||
{
|
||||
path: 'banner',
|
||||
loadChildren: () => import('./pages/setting/banner/banner.module').then(m => m.BannerModule)
|
||||
},
|
||||
{
|
||||
path: 'promotion',
|
||||
loadChildren: () => import('./pages/setting/promotion/promotion.module').then(m => m.PromotionModule)
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'not-found',
|
||||
loadChildren: () => import('./pages/errors/errors.module').then(m => m.ErrorsModule)
|
||||
|
||||
@@ -38,7 +38,8 @@ export class LoginComponent implements OnInit {
|
||||
async onSubmit(form: any) {
|
||||
if (!form.valid) return false;
|
||||
try {
|
||||
await lastValueFrom(this.authService.login(this.dataForm));
|
||||
const result = await lastValueFrom(this.authService.login(this.dataForm));
|
||||
this.appService.setAuth(result);
|
||||
return this.router.navigate(['/pages']);
|
||||
} catch (err) {
|
||||
return this.appService.message(EAction.ERROR, EText.NO_DATA);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
|
||||
import { CDialogConfig, IDialogConfig } from 'src/app/@common/interface/Dialog';
|
||||
|
||||
|
||||
export interface ResultPageEvent<T> {
|
||||
@@ -25,6 +25,8 @@ export interface CustomeEventPage extends PageEvent {
|
||||
|
||||
@Directive()
|
||||
export class BaseList {
|
||||
|
||||
dialogConfig: IDialogConfig = CDialogConfig;
|
||||
protected INT_PAGING:CustomeEventPage = {
|
||||
length: 0,
|
||||
pageIndex: 0,
|
||||
|
||||
16
src/app/core/service/common/banner.service.ts
Normal file
16
src/app/core/service/common/banner.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BaseService } from 'src/app/core/base/base-service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BannerService extends BaseService{
|
||||
|
||||
constructor(
|
||||
public http: HttpClient
|
||||
) {
|
||||
super('/common/banner', http)
|
||||
}
|
||||
|
||||
}
|
||||
16
src/app/core/service/common/promotion.service.ts
Normal file
16
src/app/core/service/common/promotion.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BaseService } from 'src/app/core/base/base-service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PromotionService extends BaseService{
|
||||
|
||||
constructor(
|
||||
public http: HttpClient
|
||||
) {
|
||||
super('/common/promotionwwwwwwwwwwww', http)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -97,7 +97,7 @@
|
||||
<i class="bi bi-person-circle"></i>
|
||||
</div>
|
||||
<div class="top-bar-user-text md:hidden">
|
||||
<div class="name">{{auth?.name || '-'}}</div>
|
||||
<div class="name">{{auth?.user_name_th || '-'}}</div>
|
||||
<div class="role"> {{auth?.email || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { KycService } from 'src/app/core/service/manage/kyc.service';
|
||||
import { KycService } from 'src/app/core/service/common/kyc.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-kyc',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { KycService } from 'src/app/core/service/manage/kyc.service';
|
||||
import { KycService } from 'src/app/core/service/common/kyc.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-transactions',
|
||||
|
||||
37
src/app/pages/setting/banner/banner.module.ts
Normal file
37
src/app/pages/setting/banner/banner.module.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { NgOptimizedImage } from "@angular/common";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { AppSharedModule } from "src/app/app.shared";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { ListComponent } from "./presenter/list/list.component";
|
||||
import { BannerRouter } from "./router/router";
|
||||
import { BannerContainer } from "./container/banner/banner.container";
|
||||
import { DialogComponent } from './presenter/dialog/dialog.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: BannerRouter,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: BannerContainer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
BannerRouter,
|
||||
BannerContainer,
|
||||
ListComponent,
|
||||
DialogComponent
|
||||
],
|
||||
imports: [
|
||||
AppSharedModule,
|
||||
NgOptimizedImage,
|
||||
RouterModule.forChild(routes)
|
||||
]
|
||||
})
|
||||
export class BannerModule { }
|
||||
@@ -0,0 +1,6 @@
|
||||
<app-list
|
||||
(add)="add()"
|
||||
(edit)="edit($event)"
|
||||
(delete)="delete($event)"
|
||||
[bannerList]="banner$ | async">
|
||||
</app-list>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BannerContainer } from './banner.container';
|
||||
|
||||
describe('BannerContainer', () => {
|
||||
let component: BannerContainer;
|
||||
let fixture: ComponentFixture<BannerContainer>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ BannerContainer ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BannerContainer);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Observable, catchError, filter, of, switchMap, tap, throwError } from 'rxjs';
|
||||
import { CDialogConfig, IDialogConfig } from 'src/app/@common/interface/Dialog';
|
||||
import { EAction, EText } from 'src/app/@config/app';
|
||||
import { BannerService } from 'src/app/core/service/common/banner.service';
|
||||
import { DialogComponent } from '../../presenter/dialog/dialog.component';
|
||||
import { AppService } from 'src/app/app.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-banner',
|
||||
templateUrl: './banner.container.html',
|
||||
styleUrls: ['./banner.container.scss']
|
||||
})
|
||||
export class BannerContainer {
|
||||
dialogConfig: IDialogConfig = CDialogConfig
|
||||
banner$ = new Observable();
|
||||
constructor(
|
||||
private bannerService: BannerService,
|
||||
private dialog: MatDialog,
|
||||
private appService: AppService
|
||||
) {
|
||||
this.banner$ = this.bannerService.getAll();
|
||||
}
|
||||
|
||||
add(){
|
||||
this.dialogConfig.data.action = EAction.CREATE;
|
||||
const dialogRef = this.dialog.open(DialogComponent,this.dialogConfig);
|
||||
dialogRef.afterClosed().pipe(
|
||||
switchMap((res) => {
|
||||
if(res === 'success'){
|
||||
return this.banner$ = this.bannerService.getAll().pipe(
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
edit(uid){
|
||||
this.dialogConfig.data.action = EAction.UPDATE;
|
||||
this.dialogConfig.data.ids = uid
|
||||
const dialogRef = this.dialog.open(DialogComponent,this.dialogConfig);
|
||||
const edit$ = dialogRef.afterClosed().pipe(
|
||||
switchMap((res) => {
|
||||
if(res === 'success'){
|
||||
return this.banner$ = this.bannerService.getAll().pipe(
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
return edit$.subscribe();
|
||||
}
|
||||
|
||||
delete(uid){
|
||||
const delete$ = this.appService.confirm(EAction.DELETE).pipe(
|
||||
filter((res) => res.isConfirmed),
|
||||
switchMap(() => {
|
||||
return this.bannerService.deleteData(uid).pipe(
|
||||
tap(() => this.appService.message(EAction.SUCCESS, EText.DELETE)),
|
||||
tap(() => this.banner$ = this.bannerService.getAll()),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.SUCCESS, EText.DELETE);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
})
|
||||
);
|
||||
return delete$.subscribe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<form [formGroup]="form" class="dialog-main form-dialog" autocomplete="off">
|
||||
<div class="dialog-main">
|
||||
<div class="dialog-header flex justify-between">
|
||||
<h2>Banner</h2>
|
||||
<mat-icon mat-dialog-close class="cursor-pointer">clear</mat-icon>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">ชื่อรายการ</mat-label>
|
||||
<mat-form-field class="col-span-7">
|
||||
<input matInput required formControlName="name" type="text">
|
||||
</mat-form-field>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">Link</mat-label>
|
||||
<mat-form-field class="col-span-3">
|
||||
<input matInput required formControlName="link" type="text">
|
||||
</mat-form-field>
|
||||
<span class="col-span-5"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label
|
||||
class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">คำอธิบาย</mat-label>
|
||||
<mat-form-field class="col-span-7">
|
||||
<textarea matInput formControlName="description" type="text"></textarea>
|
||||
</mat-form-field>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label
|
||||
class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">วันเริ่มต้น/สิ้นสุด</mat-label>
|
||||
<mat-form-field class="col-span-2">
|
||||
<input matInput formControlName="start_date" [matDatepicker]="startDate" readonly />
|
||||
<mat-datepicker-toggle [for]="startDate" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #startDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-span-2">
|
||||
<input matInput formControlName="end_date" [matDatepicker]="endDate" readonly />
|
||||
<mat-datepicker-toggle [for]="endDate" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #endDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">แนบรูป</mat-label>
|
||||
<div class="col-span-7">
|
||||
<div class="list-images" style="min-height: auto !important;" *ngIf="data">
|
||||
<div class=" grid grid-cols-12 gap-2 md:gap-2 items-center">
|
||||
<div class="col-span-2 md:col-span-4">
|
||||
<div class="flex justify-center items-center list-images-item">
|
||||
<div class="list-images-action">
|
||||
<i (click)="onRemoveAttachments()"class="bi bi-x-circle color-red cursor-pointer select-none"></i>
|
||||
</div>
|
||||
<img (click)="onAttachmentsView()" src="" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<input hidden type="file" accept="image/*" #uploadFile (change)="onAttachments($event)" />
|
||||
<button type="button" class="btn btn-sm btn-success-o" (click)="uploadFile.click()">เพิ่มแนบไฟล์</button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">Open/Close</mat-label>
|
||||
<mat-slide-toggle formControlName="is_use"></mat-slide-toggle>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="submit" mat-raised-button class="btn btn-submit" (click)="save()" [disabled]="form.invalid">บันทึก</button>
|
||||
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- <pre>{{form.getRawValue() | json}}</pre> -->
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DialogComponent } from './dialog.component';
|
||||
|
||||
describe('DialogComponent', () => {
|
||||
let component: DialogComponent;
|
||||
let fixture: ComponentFixture<DialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { catchError, tap, throwError } from 'rxjs';
|
||||
import { IDialogConfigData } from 'src/app/@common/interface/Dialog';
|
||||
import { EAction, EText } from 'src/app/@config/app';
|
||||
import { AppService } from 'src/app/app.service';
|
||||
import { BaseForm } from 'src/app/core/base/base-form';
|
||||
import { BannerService } from 'src/app/core/service/common/banner.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dialog',
|
||||
templateUrl: './dialog.component.html',
|
||||
styleUrls: ['./dialog.component.scss']
|
||||
})
|
||||
export class DialogComponent extends BaseForm implements OnInit {
|
||||
data = false;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public dialog: IDialogConfigData,
|
||||
public router: Router,
|
||||
public activatedRoute: ActivatedRoute,
|
||||
public fb: FormBuilder,
|
||||
public location: Location,
|
||||
public bannerService: BannerService,
|
||||
public appService: AppService,
|
||||
public cdr: ChangeDetectorRef
|
||||
) {
|
||||
super(router, activatedRoute, fb, location)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.dialog.action === EAction.UPDATE){
|
||||
this.state = 'edit';
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
|
||||
createForm(): FormGroup<any> {
|
||||
return this.fb.group({
|
||||
status_id: null,
|
||||
created_by: null,
|
||||
created_datetime: null,
|
||||
updated_by: null,
|
||||
updated_datetime: null,
|
||||
owner_agency_uid: null,
|
||||
banner_uid: null,
|
||||
name: [null, Validators.required],
|
||||
link: [null, Validators.required],
|
||||
description: null,
|
||||
start_date: [null, Validators.required],
|
||||
end_date: [null, Validators.required],
|
||||
file_name: null,
|
||||
file_url: [null],
|
||||
is_use: false
|
||||
})
|
||||
}
|
||||
|
||||
getData() {
|
||||
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
|
||||
this.bannerService.get(this.dialog.ids).pipe(
|
||||
tap((res) => this.form.patchValue(res)),
|
||||
tap(() => this.cdr.detectChanges()),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
save() {
|
||||
const form = this.form.getRawValue();
|
||||
const save$ = this.state === 'edit' ? this.bannerService.update2(form) : this.bannerService.add(form);
|
||||
return save$.pipe(
|
||||
tap(() => this.appService.message(EAction.SUCCESS, EText.UPDATE)),
|
||||
tap(() => this.dialogRef.close('success')),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
// async onSubmit(form: any) {
|
||||
// if (!form.valid) return false;
|
||||
|
||||
// const sweetalert = await lastValueFrom(this.appService.confirm(EAction.CREATE));
|
||||
// if (!sweetalert.isConfirmed) return;
|
||||
|
||||
// this.dataForm.images = this.attachments?.[0] ? this.attachments.join(",") : null;
|
||||
|
||||
// this.dataForm.pageAction = 'financePaying';
|
||||
// return await this.onUpdate();
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// async onUpdate() {
|
||||
// try {
|
||||
// await lastValueFrom(this.appService.post(`${this.api.quotation}/update/${this.ids}`, this.dataForm));
|
||||
// await this.appService.message(EAction.SUCCESS, EText.UPDATE);
|
||||
// await this.router.navigate(["/pages/finance/paying/list", this.action]);
|
||||
// } catch (err) {
|
||||
// this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
async onAttachments($event: any) {
|
||||
const file = $event.target.files[0];
|
||||
if (!file) return;
|
||||
const formData = new FormData();
|
||||
formData.append("ref", 'images');
|
||||
formData.append("file", file);
|
||||
// try {
|
||||
// const res = await lastValueFrom(this.appService.post(`${API.attachments}/images`, formData));
|
||||
// this.dataForm.sellerPaymentImages = res.fileName;
|
||||
// this.uploadFile.nativeElement.value = null;
|
||||
// this.changeDetectorRef.detectChanges();
|
||||
// } catch (e) {
|
||||
// this.appService.message(EText.ERROR);
|
||||
// }
|
||||
}
|
||||
|
||||
async onRemoveAttachments() {
|
||||
// const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
|
||||
// if (!sweetalert.isConfirmed) return;
|
||||
// this.dataForm.paymentImages = null;
|
||||
// this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
async onAttachmentsView() {
|
||||
// const dialogConfig = deepCopy(this.dialogConfig);
|
||||
// dialogConfig.data.action = EAction.POPUP;
|
||||
// dialogConfig.data.title = 'ไฟล์แนบ';
|
||||
// dialogConfig.data.type = 'images';
|
||||
// dialogConfig.data.images = this.dataForm.sellerPaymentImages;
|
||||
// const dialogRef = this.attachmentsView.open(AttachmentsViewComponent, dialogConfig);
|
||||
// const afterClosed = await lastValueFrom(dialogRef.afterClosed());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<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-4 md:col-span-6">
|
||||
<mat-form-field>
|
||||
<i matTextPrefix class="bi bi-search"></i>
|
||||
<input matInput placeholder="ชื่อรายการ">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-span-8 md:col-span-6">
|
||||
<button type="button" class="btn btn-create" (click)="onAdd()">
|
||||
<i class="bi bi-plus"></i>
|
||||
เพิ่มรายการ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="table-wrap">
|
||||
<table class="table table-main" mat-table [dataSource]="bannerList" matSort>
|
||||
<tr mat-header-row *matHeaderRowDef="['1','2','3','4','5','6','7','8']"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['1','2','3','4','5','6','7','8'];"></tr>
|
||||
|
||||
<ng-container matColumnDef="1">
|
||||
<th mat-header-cell *matHeaderCellDef class="tac" mat-sort-header>ลำดับ</th>
|
||||
<td mat-cell *matCellDef="let item; let i = index" width="150" class="tac">{{getIndex(i)}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="2">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อรายการ</th>
|
||||
<td mat-cell *matCellDef="let item" class="" style="min-width: 200px;">
|
||||
{{item.name}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="3">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" mat-sort-header>Link</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.link}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="4">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" mat-sort-header>คำอธิบาย</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.description}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="5">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">วันเริ่มต้น</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.start_date | date : 'dd/MM/YYYY'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="6">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">วันสิ้นสุด</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.weight | date : 'dd/MM/YYYY'}}</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<ng-container matColumnDef="7">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">สถานะ</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.is_use === true? 'Open' : 'Close'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="8">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">เครื่องมือ</th>
|
||||
<td mat-cell *matCellDef="let item" class="">
|
||||
<div class="action flex justify-center">
|
||||
<div class="item">
|
||||
<i class="bi bi-filetype-pdf color-main" (click)="onEdit(item.banner_uid)"></i>
|
||||
</div>
|
||||
<div class="item">
|
||||
<i class="bi bi-trash3 color-red" (click)="onDelete(item.banner_uid)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<!-- <div *ngIf="dataSourceCount === 0" class="no-data"></div> -->
|
||||
<mat-paginator [pageSizeOptions]="[5,10,20]" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ListComponent } from './list.component';
|
||||
|
||||
describe('ListComponent', () => {
|
||||
let component: ListComponent;
|
||||
let fixture: ComponentFixture<ListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
import { DialogComponent } from '../dialog/dialog.component';
|
||||
import { BaseList } from 'src/app/core/base/base-list';
|
||||
import { EAction } from 'src/app/@config/app';
|
||||
import { filter, lastValueFrom, switchMap, tap } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-list',
|
||||
templateUrl: './list.component.html',
|
||||
styleUrls: ['./list.component.scss']
|
||||
})
|
||||
export class ListComponent extends BaseList implements OnChanges {
|
||||
@Input() bannerList: any = [];
|
||||
@Output() add = new EventEmitter();
|
||||
@Output() edit = new EventEmitter();
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
ngOnChanges(){
|
||||
this.bannerList = this.updateMatTable(this.bannerList? this.bannerList : [])
|
||||
}
|
||||
|
||||
onAdd() {
|
||||
this.add.emit()
|
||||
}
|
||||
|
||||
onEdit(uid){
|
||||
this.edit.emit(uid)
|
||||
}
|
||||
}
|
||||
16
src/app/pages/setting/banner/router/router.ts
Normal file
16
src/app/pages/setting/banner/router/router.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-banner-router',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class BannerRouter implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<app-list
|
||||
(add)="add()"
|
||||
(edit)="edit($event)"
|
||||
(delete)="delete($event)"
|
||||
[promotionList]="promotion$ | async">
|
||||
</app-list>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PromotionContainer } from './promotion.container';
|
||||
|
||||
describe('PromotionContainer', () => {
|
||||
let component: PromotionContainer;
|
||||
let fixture: ComponentFixture<PromotionContainer>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PromotionContainer ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PromotionContainer);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable, catchError, filter, switchMap, tap, throwError } from 'rxjs';
|
||||
import { IDialogConfig, CDialogConfig } from 'src/app/@common/interface/Dialog';
|
||||
import { EAction, EText } from 'src/app/@config/app';
|
||||
import { PromotionService } from 'src/app/core/service/common/promotion.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AppService } from 'src/app/app.service';
|
||||
import { DialogComponent } from '../../presenter/dialog/dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-promotion',
|
||||
templateUrl: './promotion.container.html',
|
||||
styleUrls: ['./promotion.container.scss']
|
||||
})
|
||||
export class PromotionContainer {
|
||||
dialogConfig: IDialogConfig = CDialogConfig
|
||||
promotion$ = new Observable();
|
||||
constructor(
|
||||
private promotionSerivce: PromotionService,
|
||||
private dialog: MatDialog,
|
||||
private appService: AppService
|
||||
) {
|
||||
this.promotion$ = this.promotionSerivce.getAll();
|
||||
}
|
||||
|
||||
add(){
|
||||
this.dialogConfig.data.action = EAction.CREATE;
|
||||
const dialogRef = this.dialog.open(DialogComponent,this.dialogConfig);
|
||||
dialogRef.afterClosed().pipe(
|
||||
switchMap((res) => {
|
||||
if(res === 'success'){
|
||||
return this.promotion$ = this.promotionSerivce.getAll().pipe(
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
edit(uid){
|
||||
this.dialogConfig.data.action = EAction.UPDATE;
|
||||
this.dialogConfig.data.ids = uid
|
||||
const dialogRef = this.dialog.open(DialogComponent,this.dialogConfig);
|
||||
const edit$ = dialogRef.afterClosed().pipe(
|
||||
switchMap((res) => {
|
||||
if(res === 'success'){
|
||||
return this.promotion$ = this.promotionSerivce.getAll().pipe(
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
return edit$.subscribe()
|
||||
}
|
||||
|
||||
delete(uid){
|
||||
const delete$ = this.appService.confirm(EAction.DELETE).pipe(
|
||||
filter((res) => res.isConfirmed),
|
||||
switchMap(() => {
|
||||
return this.promotionSerivce.deleteData(uid).pipe(
|
||||
tap(() => this.appService.message(EAction.SUCCESS, EText.DELETE)),
|
||||
tap(() => this.promotion$ = this.promotionSerivce.getAll()),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.SUCCESS, EText.DELETE);
|
||||
return throwError(() => err)
|
||||
})
|
||||
)
|
||||
})
|
||||
);
|
||||
return delete$.subscribe()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<form [formGroup]="form" class="dialog-main form-dialog" autocomplete="off">
|
||||
<div class="dialog-main">
|
||||
<div class="dialog-header flex justify-between">
|
||||
<h2>Promotion</h2>
|
||||
<mat-icon mat-dialog-close class="cursor-pointer">clear</mat-icon>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<div class="grid grid-cols-12 gap-4 md:gap-2 ">
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">ชื่อรายการ</mat-label>
|
||||
<mat-form-field class="col-span-7">
|
||||
<input matInput required formControlName="name" type="text">
|
||||
</mat-form-field>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">Link</mat-label>
|
||||
<mat-form-field class="col-span-3">
|
||||
<input matInput required formControlName="link" type="text">
|
||||
</mat-form-field>
|
||||
<span class="col-span-5"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label
|
||||
class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">คำอธิบาย</mat-label>
|
||||
<mat-form-field class="col-span-7">
|
||||
<textarea matInput formControlName="description" type="text"></textarea>
|
||||
</mat-form-field>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label
|
||||
class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">วันเริ่มต้น/สิ้นสุด</mat-label>
|
||||
<mat-form-field class="col-span-2">
|
||||
<input matInput formControlName="start_date" [matDatepicker]="startDate" readonly />
|
||||
<mat-datepicker-toggle [for]="startDate" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #startDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-span-2">
|
||||
<input matInput formControlName="end_date" [matDatepicker]="endDate" readonly />
|
||||
<mat-datepicker-toggle [for]="endDate" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #endDate></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">แนบรูป</mat-label>
|
||||
<div class="col-span-7">
|
||||
<div class="list-images" style="min-height: auto !important;" *ngIf="data">
|
||||
<div class=" grid grid-cols-12 gap-2 md:gap-2 items-center">
|
||||
<div class="col-span-2 md:col-span-4">
|
||||
<div class="flex justify-center items-center list-images-item">
|
||||
<div class="list-images-action">
|
||||
<i (click)="onRemoveAttachments()"class="bi bi-x-circle color-red cursor-pointer select-none"></i>
|
||||
</div>
|
||||
<img (click)="onAttachmentsView()" src="" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<input hidden type="file" accept="image/*" #uploadFile (change)="onAttachments($event)" />
|
||||
<button type="button" class="btn btn-sm btn-success-o" (click)="uploadFile.click()">เพิ่มแนบไฟล์</button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-full">
|
||||
<div class="lg:flex lg:flex-col grid grid-cols-9 gap-2">
|
||||
<mat-label class="col-span-1 lg:text-left lg:self-auto text-right self-center mr-4">Open/Close</mat-label>
|
||||
<mat-slide-toggle formControlName="is_use"></mat-slide-toggle>
|
||||
<span class="col-span-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="submit" mat-raised-button class="btn btn-submit" (click)="save()" [disabled]="form.invalid">บันทึก</button>
|
||||
<button type="button" mat-dialog-close class="btn btn-dialog-close">ยกเลิก</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- <pre>{{form.getRawValue() | json}}</pre> -->
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DialogComponent } from './dialog.component';
|
||||
|
||||
describe('DialogComponent', () => {
|
||||
let component: DialogComponent;
|
||||
let fixture: ComponentFixture<DialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { catchError, tap, throwError } from 'rxjs';
|
||||
import { IDialogConfigData } from 'src/app/@common/interface/Dialog';
|
||||
import { EAction, EText } from 'src/app/@config/app';
|
||||
import { AppService } from 'src/app/app.service';
|
||||
import { BaseForm } from 'src/app/core/base/base-form';
|
||||
import { PromotionService } from 'src/app/core/service/common/promotion.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dialog',
|
||||
templateUrl: './dialog.component.html',
|
||||
styleUrls: ['./dialog.component.scss']
|
||||
})
|
||||
export class DialogComponent extends BaseForm implements OnInit {
|
||||
data = false;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public dialog: IDialogConfigData,
|
||||
public router: Router,
|
||||
public activatedRoute: ActivatedRoute,
|
||||
public fb: FormBuilder,
|
||||
public location: Location,
|
||||
public promotionService: PromotionService,
|
||||
public appService: AppService,
|
||||
public cdr: ChangeDetectorRef
|
||||
) {
|
||||
super(router, activatedRoute, fb, location)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.dialog.action === EAction.UPDATE){
|
||||
this.state = 'edit';
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
|
||||
createForm(): FormGroup<any> {
|
||||
return this.fb.group({
|
||||
status_id: null,
|
||||
created_by: null,
|
||||
created_datetime: null,
|
||||
updated_by: null,
|
||||
updated_datetime: null,
|
||||
owner_agency_uid: null,
|
||||
promotion_uid: null,
|
||||
name: [null, Validators.required],
|
||||
link: [null, Validators.required],
|
||||
description: null,
|
||||
start_date: [null, Validators.required],
|
||||
end_date: [null, Validators.required],
|
||||
file_name: null,
|
||||
file_url: [null],
|
||||
is_use: false
|
||||
})
|
||||
}
|
||||
|
||||
getData() {
|
||||
if (!this.dialog.ids) this.appService.message(EAction.INFO, EText.NO_DATA);
|
||||
this.promotionService.get(this.dialog.ids).pipe(
|
||||
tap((res) => this.form.patchValue(res)),
|
||||
tap(() => this.cdr.detectChanges()),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
save() {
|
||||
const form = this.form.getRawValue();
|
||||
const save$ = this.state === 'edit' ? this.promotionService.update2(form) : this.promotionService.add(form);
|
||||
return save$.pipe(
|
||||
tap(() => this.appService.message(EAction.SUCCESS, EText.UPDATE)),
|
||||
tap(() => this.dialogRef.close('success')),
|
||||
catchError((err) => {
|
||||
this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
return throwError(() => err)
|
||||
})
|
||||
).subscribe()
|
||||
}
|
||||
|
||||
// async onSubmit(form: any) {
|
||||
// if (!form.valid) return false;
|
||||
|
||||
// const sweetalert = await lastValueFrom(this.appService.confirm(EAction.CREATE));
|
||||
// if (!sweetalert.isConfirmed) return;
|
||||
|
||||
// this.dataForm.images = this.attachments?.[0] ? this.attachments.join(",") : null;
|
||||
|
||||
// this.dataForm.pageAction = 'financePaying';
|
||||
// return await this.onUpdate();
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// async onUpdate() {
|
||||
// try {
|
||||
// await lastValueFrom(this.appService.post(`${this.api.quotation}/update/${this.ids}`, this.dataForm));
|
||||
// await this.appService.message(EAction.SUCCESS, EText.UPDATE);
|
||||
// await this.router.navigate(["/pages/finance/paying/list", this.action]);
|
||||
// } catch (err) {
|
||||
// this.appService.message(EAction.ERROR, EText.ERROR);
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
async onAttachments($event: any) {
|
||||
const file = $event.target.files[0];
|
||||
if (!file) return;
|
||||
const formData = new FormData();
|
||||
formData.append("ref", 'images');
|
||||
formData.append("file", file);
|
||||
// try {
|
||||
// const res = await lastValueFrom(this.appService.post(`${API.attachments}/images`, formData));
|
||||
// this.dataForm.sellerPaymentImages = res.fileName;
|
||||
// this.uploadFile.nativeElement.value = null;
|
||||
// this.changeDetectorRef.detectChanges();
|
||||
// } catch (e) {
|
||||
// this.appService.message(EText.ERROR);
|
||||
// }
|
||||
}
|
||||
|
||||
async onRemoveAttachments() {
|
||||
// const sweetalert = await lastValueFrom(this.appService.confirm(EAction.DELETE));
|
||||
// if (!sweetalert.isConfirmed) return;
|
||||
// this.dataForm.paymentImages = null;
|
||||
// this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
async onAttachmentsView() {
|
||||
// const dialogConfig = deepCopy(this.dialogConfig);
|
||||
// dialogConfig.data.action = EAction.POPUP;
|
||||
// dialogConfig.data.title = 'ไฟล์แนบ';
|
||||
// dialogConfig.data.type = 'images';
|
||||
// dialogConfig.data.images = this.dataForm.sellerPaymentImages;
|
||||
// const dialogRef = this.attachmentsView.open(AttachmentsViewComponent, dialogConfig);
|
||||
// const afterClosed = await lastValueFrom(dialogRef.afterClosed());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<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-4 md:col-span-6">
|
||||
<mat-form-field>
|
||||
<i matTextPrefix class="bi bi-search"></i>
|
||||
<input matInput placeholder="ชื่อรายการ">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-span-8 md:col-span-6">
|
||||
<button type="button" class="btn btn-create" (click)="onAdd()">
|
||||
<i class="bi bi-plus"></i>
|
||||
เพิ่มรายการ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="table-wrap">
|
||||
<table class="table table-main" mat-table [dataSource]="promotionList" matSort>
|
||||
<tr mat-header-row *matHeaderRowDef="['1','2','3','4','5','6','7','8']"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['1','2','3','4','5','6','7','8'];"></tr>
|
||||
|
||||
<ng-container matColumnDef="1">
|
||||
<th mat-header-cell *matHeaderCellDef class="tac" mat-sort-header>ลำดับ</th>
|
||||
<td mat-cell *matCellDef="let item; let i = index" width="150" class="tac">{{getIndex(i)}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="2">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal">ชื่อรายการ</th>
|
||||
<td mat-cell *matCellDef="let item" class="" style="min-width: 200px;">
|
||||
{{item.name}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="3">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" mat-sort-header>Link</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.link}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="4">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" mat-sort-header>คำอธิบาย</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.description}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="5">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">วันเริ่มต้น</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.start_date | date : 'dd/MM/YYYY'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="6">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">วันสิ้นสุด</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.weight | date : 'dd/MM/YYYY'}}</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<ng-container matColumnDef="7">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">สถานะ</th>
|
||||
<td mat-cell *matCellDef="let item" class="">{{item.is_use === true? 'Open' : 'Close'}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="8">
|
||||
<th mat-header-cell *matHeaderCellDef class="tal" width="150">เครื่องมือ</th>
|
||||
<td mat-cell *matCellDef="let item" class="">
|
||||
<div class="action flex justify-center">
|
||||
<div class="item">
|
||||
<i class="bi bi-filetype-pdf color-main" (click)="onEdit(item.promotion_uid)"></i>
|
||||
</div>
|
||||
<div class="item">
|
||||
<i class="bi bi-trash3 color-red" (click)="onDelete(item.promotion_uid)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<!-- <div *ngIf="dataSourceCount === 0" class="no-data"></div> -->
|
||||
<mat-paginator [pageSizeOptions]="[5,10,20]" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ListComponent } from './list.component';
|
||||
|
||||
describe('ListComponent', () => {
|
||||
let component: ListComponent;
|
||||
let fixture: ComponentFixture<ListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
import { BaseList } from 'src/app/core/base/base-list';
|
||||
|
||||
@Component({
|
||||
selector: 'app-list',
|
||||
templateUrl: './list.component.html',
|
||||
styleUrls: ['./list.component.scss']
|
||||
})
|
||||
export class ListComponent extends BaseList implements OnChanges {
|
||||
@Input() promotionList: any = [];
|
||||
@Output() add = new EventEmitter();
|
||||
@Output() edit = new EventEmitter();
|
||||
@Output() delete = new EventEmitter();
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
ngOnChanges(){
|
||||
this.promotionList = this.updateMatTable(this.promotionList? this.promotionList : [])
|
||||
}
|
||||
|
||||
onAdd(){
|
||||
this.add.emit()
|
||||
}
|
||||
|
||||
onEdit(uid: string){
|
||||
this.edit.emit(uid)
|
||||
}
|
||||
|
||||
onDelete(uid){
|
||||
this.delete.emit(uid)
|
||||
}
|
||||
}
|
||||
37
src/app/pages/setting/promotion/promotion.module.ts
Normal file
37
src/app/pages/setting/promotion/promotion.module.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { NgOptimizedImage } from "@angular/common";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
import { AppSharedModule } from "src/app/app.shared";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { ListComponent } from "./presenter/list/list.component";
|
||||
import { PromotionRouter } from "./router/router";
|
||||
import { PromotionContainer } from "./container/promotion/promotion.container";
|
||||
import { DialogComponent } from './presenter/dialog/dialog.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PromotionRouter,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: PromotionContainer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
PromotionRouter,
|
||||
PromotionContainer,
|
||||
ListComponent,
|
||||
DialogComponent
|
||||
],
|
||||
imports: [
|
||||
AppSharedModule,
|
||||
NgOptimizedImage,
|
||||
RouterModule.forChild(routes)
|
||||
]
|
||||
})
|
||||
export class PromotionModule { }
|
||||
16
src/app/pages/setting/promotion/router/router.ts
Normal file
16
src/app/pages/setting/promotion/router/router.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-promotion-router',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class PromotionRouter implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -91,6 +91,10 @@ h3, h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
mat-label{
|
||||
color: #3D8A8B
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// material
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user