Commit c71538b8 by Nakarin Luankla

Merge branch 'DEV' of https://mygit.myhr.co.th/angular/myAppraisal into DEV

parents 1c0dc14d 7e33ed6d
...@@ -181,9 +181,9 @@ ...@@ -181,9 +181,9 @@
</div> </div>
</div> </div>
<ng-container *ngIf="changePassword"> <ng-container *ngIf="changePassword">
<label class="ti-form-label mt-2rem">รหัสผ่านเก่า</label> <label class="ti-form-label mt-2rem">รหัสผ่านเก่า*</label>
<input type="password" class="ti-form-input" [(ngModel)]="userPassword.oldPassword"> <input type="password" class="ti-form-input" [(ngModel)]="userPassword.oldPassword">
<label class="ti-form-label mt-2rem">รหัสผ่านใหม่</label> <label class="ti-form-label mt-2rem">รหัสผ่านใหม่*</label>
<input type="password" class="ti-form-input" [(ngModel)]="userPassword.newPassword"> <input type="password" class="ti-form-input" [(ngModel)]="userPassword.newPassword">
</ng-container> </ng-container>
<div class="flex justify-end mt-2rem mb-1rem"> <div class="flex justify-end mt-2rem mb-1rem">
...@@ -193,8 +193,8 @@ ...@@ -193,8 +193,8 @@
ย้อนกลับ ย้อนกลับ
</button> </button>
<button type="button" class="ti-btn ti-btn-success" data-hs-overlay="#manage-user-alert-modal" <button type="button" class="ti-btn ti-btn-success" data-hs-overlay="#manage-user-alert-modal"
[class.ti-btn-disabled]="changePassword&&!userPassword.newPassword" [class.ti-btn-disabled]="changePassword&&(!userPassword.newPassword || !userPassword.oldPassword)"
[disabled]="changePassword&&!userPassword.newPassword"> [disabled]="changePassword&&(!userPassword.newPassword||!userPassword.oldPassword)">
บันทึกข้อมูล บันทึกข้อมูล
</button> </button>
</div> </div>
......
...@@ -84,52 +84,6 @@ export class SetAPasswordComponent { ...@@ -84,52 +84,6 @@ export class SetAPasswordComponent {
newPassword: "", newPassword: "",
} }
} }
onFileSelected(event: any) {
this.selectedFile = event.target.files.length > 0 ? event.target.files[0] : null;
this.selectedFileName = this.selectedFile?.name || "กรุณาเลือกไฟล์"
}
uploadFile() {
if (!this.selectedFile) {
alert('กรุณาเลือกไฟล์ก่อนอัปโหลด')
return
}
const formData = new FormData();
formData.append('file', this.selectedFile);
this.user.loading = true
this.fileService.upload(formData, 'mbu1').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getUserList()
} else {
this.showAlert(response.message, 'error')
this.user.loading = false
}
}, error: error => {
this.showAlert(error.message, 'error')
this.user.loading = false
}
})
}
downloadFile() {
const fileName = 'IMPORT_USER.xlsx'
this.fileService.download(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
updateUserPassword() { updateUserPassword() {
this.user.loading = true this.user.loading = true
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
นำเข้าข้อมูล นำเข้าข้อมูล
</button> </button>
<a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end" <a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end"
href="javascript:void(0);"> href="javascript:void(0);" (click)="downloadFile()">
ดาวน์โหลดตัวอย่างไฟล์ ดาวน์โหลดตัวอย่างไฟล์
</a> </a>
</div> </div>
......
...@@ -178,7 +178,7 @@ export class UserSettingsComponent { ...@@ -178,7 +178,7 @@ export class UserSettingsComponent {
const formData = new FormData(); const formData = new FormData();
formData.append('file', this.selectedFile); formData.append('file', this.selectedFile);
this.user.loading = true this.user.loading = true
this.fileService.upload(formData, 'mbu1').subscribe({ this.fileService.upload(formData, 'muser').subscribe({
next: response => { next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success') this.showAlert(response.message, 'success')
......
<div class="w-full min-height-50px mb-10px justify-between items-center"> <div class="w-full min-height-50px mb-10px justify-between items-center">
<div class="flex pr-2 pb-2rem">
<div class="flex">
<div class="flex items-center">
<input type="checkbox" class="ti-form-checkbox pointer-events-none" id="hs-default-checkbox"
[(ngModel)]="isDataListChecked">
<label for="hs-default-checkbox" class="text-sm text-gray-500 mx-2 pointer-events-none">
{{numDataListChecked}} Selected</label>
</div>
<div class="mx-1 flex items-center">
<button (click)="isDataListCheckedAll = !isDataListCheckedAll;dataListCheckAll()"
class="focus:ring-2 focus:ring-primary rounded-sm flex item-center">
<i class="fs-l transition-all duration-200"
[ngClass]="{'ri-checkbox-multiple-line text-gray-500': !isDataListCheckedAll, 'ri-checkbox-multiple-fill text-primary': isDataListCheckedAll}"></i>
</button>
<label class="text-sm text-gray-500 ml-2">Select All</label>
</div>
</div>
</div>
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex pr-2"> <div class="flex pr-2">
<div class="px-1"> <div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md" <button type="button" class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
data-hs-overlay="#company-registration-page-upload-modal"> data-hs-overlay="#company-registration-page-upload-modal"
(click)="fileInput.value = '';selectedFile=null;selectedFileName = 'กรุณาเลือกไฟล์'">
<i class="ri-add-line"></i> <i class="ri-add-line"></i>
นำเข้าข้อมูล นำเข้าข้อมูล
</button> </button>
<a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end" <a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end"
href="javascript:void(0);"> href="javascript:void(0);" (click)="downloadFile()">
ดาวน์โหลดตัวอย่างไฟล์ ดาวน์โหลดตัวอย่างไฟล์
</a> </a>
</div> </div>
...@@ -88,7 +107,7 @@ ...@@ -88,7 +107,7 @@
*ngFor="let item of dataListFilter() | slice:((currentPage-1) * 10) : (((currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of dataListFilter() | slice:((currentPage-1) * 10) : (((currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
<input *ngIf="item.data.code!='100'" type="checkbox" class="ti-form-checkbox cursor-pointer" <input *ngIf="item.data.code!='100'" type="checkbox" class="ti-form-checkbox cursor-pointer"
id="checkbox-{{item.data.code}}" [(ngModel)]="item.check"> id="checkbox-{{item.data.code}}" [(ngModel)]="item.check" (ngModelChange)="dataListCheck()">
<label for="checkbox-{{item.data.code}}">&nbsp;{{item.data.code}}</label> <label for="checkbox-{{item.data.code}}">&nbsp;{{item.data.code}}</label>
</td> </td>
<td>{{item.data.tdesc}}</td> <td>{{item.data.tdesc}}</td>
...@@ -164,7 +183,7 @@ ...@@ -164,7 +183,7 @@
<div class="w-full flex justify-end"> <div class="w-full flex justify-end">
<div class="absolute flex"> <div class="absolute flex">
<div class="px-1"> <div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-indigo h-45px m-0 shadow-md"> <button type="button" class="ti-btn ti-btn-soft-indigo h-45px m-0 shadow-md" (click)="clearData()">
<svg class="svg-indigo" width="16" height="16" viewBox="0 0 64.00 64.00" <svg class="svg-indigo" width="16" height="16" viewBox="0 0 64.00 64.00"
xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#595BEA" stroke-width="3.84" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#595BEA" stroke-width="3.84"
transform="rotate(45)matrix(-1, 0, 0, 1, 0, 0)"> transform="rotate(45)matrix(-1, 0, 0, 1, 0, 0)">
...@@ -189,11 +208,11 @@ ...@@ -189,11 +208,11 @@
</div> </div>
</div> </div>
<div class="ti-modal-body padding-16px pt-0 overflow-y-0"> <div class="ti-modal-body padding-16px pt-0 overflow-y-0">
<label for="input-label" class="ti-form-label mt-2rem">รหัสบริษัท *</label> <label for="input-label" class="ti-form-label mt-2rem">รหัสบริษัท*</label>
<input type="text" id="input-label" class="ti-form-input w-1/2" <input type="text" id="input-label" class="ti-form-input w-1/2"
[ngClass]="{'bg-input-readonly':modalStatus=='edit'}" [readonly]="modalStatus=='edit'" [ngClass]="{'bg-input-readonly':modalStatus=='edit'}" [readonly]="modalStatus=='edit'"
[(ngModel)]="dataSelect.code" [maxLength]="5"> [(ngModel)]="dataSelect.code" [maxLength]="5">
<label for="detail_th" class="ti-form-label mt-2rem">รายละเอียด (ไทย) *</label> <label for="detail_th" class="ti-form-label mt-2rem">รายละเอียด (ไทย)*</label>
<input type="text" id="detail_th" class="ti-form-input h-16" [(ngModel)]="dataSelect.tdesc"> <input type="text" id="detail_th" class="ti-form-input h-16" [(ngModel)]="dataSelect.tdesc">
<label for="detail_eng" class="ti-form-label mt-2rem">รายละเอียด (อังกฤษ)</label> <label for="detail_eng" class="ti-form-label mt-2rem">รายละเอียด (อังกฤษ)</label>
<input type="text" id="detail_eng" class="ti-form-input h-16" [(ngModel)]="dataSelect.edesc"> <input type="text" id="detail_eng" class="ti-form-input h-16" [(ngModel)]="dataSelect.edesc">
...@@ -207,10 +226,12 @@ ...@@ -207,10 +226,12 @@
data-hs-overlay="#company-registration-page-modal"> data-hs-overlay="#company-registration-page-modal">
ย้อนกลับ ย้อนกลับ
</button> </button>
<a class="ti-btn ti-btn-success" href="javascript:void(0);" <button type="button" class="ti-btn ti-btn-success"
data-hs-overlay="#company-registration-page-alert-modal"> data-hs-overlay="#company-registration-page-alert-modal"
[class.ti-btn-disabled]="!dataSelect.code||!dataSelect.tdesc"
[disabled]="!dataSelect.code||!dataSelect.tdesc">
บันทึกข้อมูล บันทึกข้อมูล
</a> </button>
</div> </div>
</div> </div>
</div> </div>
...@@ -291,18 +312,20 @@ ...@@ -291,18 +312,20 @@
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1> <h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2"> <div class="mt-2 p-2">
<div class="flex rounded-md"> <div class="flex rounded-md">
<input type="text" id="hs-trailing-button-add-on-with-icon" <input #fileInput id="fileInput" type="file" (change)="onFileSelected($event)" hidden>
name="hs-trailing-button-add-on-with-icon" <input type="text" [value]="selectedFileName" readonly (click)="fileInput.click()"
class="ti-form-input rounded-none ltr:rounded-l-md rtl:rounded-r-md focus:z-10"> class="ti-form-input rounded-none ltr:rounded-l-md rtl:rounded-r-md focus:z-10 cursor-pointer">
<button aria-label="button" type="button" <button type="button" (click)="fileInput.click()"
class="inline-flex flex-shrink-0 justify-center items-center h-[2.875rem] w-[2.875rem] ltr:rounded-r-md rtl:rounded-l-md border border-transparent font-semibold bg-secondary text-white hover:bg-secondary focus:z-10 focus:outline-none focus:ring-0 focus:ring-secondary transition-all text-sm"> class="inline-flex flex-shrink-0 justify-center items-center h-[2.875rem] w-[2.875rem] ltr:rounded-r-md rtl:rounded-l-md border border-transparent font-semibold bg-secondary text-white hover:bg-secondary focus:z-10 focus:outline-none focus:ring-0 focus:ring-secondary transition-all text-sm">
<i class="ti ti-upload"></i> <i class="ti ti-upload"></i>
</button> </button>
</div> </div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4"> <div class="flex justify-center mt-2rem mb-1rem space-x-4">
<a class="ti-btn ti-btn-secondary" href="javascript:void(0);"> <button type="submit" class="ti-btn ti-btn-secondary"
data-hs-overlay="#position-unit-component-upload-modal" [class.ti-btn-disabled]="!selectedFile"
(click)="uploadFile()" [disabled]="!selectedFile" [disabled]="!selectedFile">
อัปโหลด อัปโหลด
</a> </button>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component } from '@angular/core'; ...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component } from '@angular/core';
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { CompanyModel, MyCompanyModel } from 'src/app/shared/model/company.model'; import { CompanyModel, MyCompanyModel } from 'src/app/shared/model/company.model';
import { CompanyService } from 'src/app/shared/services/company.service'; import { CompanyService } from 'src/app/shared/services/company.service';
import { FileService } from 'src/app/shared/services/file.service';
export interface DataModel { export interface DataModel {
code: string code: string
tdesc: string tdesc: string
...@@ -23,11 +24,16 @@ export class CompanyRegistrationPageComponent { ...@@ -23,11 +24,16 @@ export class CompanyRegistrationPageComponent {
dataLoading = false dataLoading = false
dataSelect: DataModel = { code: "", tdesc: "", edesc: "", address: "", contact: "" } dataSelect: DataModel = { code: "", tdesc: "", edesc: "", address: "", contact: "" }
numDataListChecked = 0
isDataListChecked = false
isDataListCheckedAll = false
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
constructor(private toastr: ToastrService, constructor(private toastr: ToastrService,
private companyService: CompanyService, private companyService: CompanyService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
) { private fileService: FileService) { }
}
ngOnInit(): void { ngOnInit(): void {
this.getCompanyList() this.getCompanyList()
} }
...@@ -38,6 +44,8 @@ export class CompanyRegistrationPageComponent { ...@@ -38,6 +44,8 @@ export class CompanyRegistrationPageComponent {
next: response => { next: response => {
this.dataList = response.map(x => ({ check: false, data: { code: x.companyId, tdesc: x.tdesc, edesc: x.edesc, address: x.addressText, contact: x.descOther } })) this.dataList = response.map(x => ({ check: false, data: { code: x.companyId, tdesc: x.tdesc, edesc: x.edesc, address: x.addressText, contact: x.descOther } }))
this.dataLoading = false this.dataLoading = false
this.isDataListCheckedAll = false
this.dataListCheckAll()
this.searchChange() this.searchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => { }, error: error => {
...@@ -50,6 +58,7 @@ export class CompanyRegistrationPageComponent { ...@@ -50,6 +58,7 @@ export class CompanyRegistrationPageComponent {
searchChange() { searchChange() {
this.currentPage = 1 this.currentPage = 1
this.page = Array.from({ length: Math.ceil(this.dataListFilter().length / 10) }, (_, i) => i + 1); this.page = Array.from({ length: Math.ceil(this.dataListFilter().length / 10) }, (_, i) => i + 1);
this.dataListCheck()
} }
dataListFilter() { dataListFilter() {
return this.dataList.filter(x => { return this.dataList.filter(x => {
...@@ -82,7 +91,7 @@ export class CompanyRegistrationPageComponent { ...@@ -82,7 +91,7 @@ export class CompanyRegistrationPageComponent {
if (this.dataSelect.code) { if (this.dataSelect.code) {
body = new MyCompanyModel({ companyId: this.dataSelect.code, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, addressText: this.dataSelect.address, descOther: this.dataSelect.contact }) body = new MyCompanyModel({ companyId: this.dataSelect.code, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, addressText: this.dataSelect.address, descOther: this.dataSelect.contact })
} else { } else {
body = this.dataList.filter(x => x.check).map(x => new MyCompanyModel({ companyId: x.data.code, tdesc: x.data.tdesc, edesc: x.data.edesc, addressText: x.data.address, descOther: x.data.contact })) body = this.dataList.filter(x => x.check && x.data.code != '100').map(x => new MyCompanyModel({ companyId: x.data.code, tdesc: x.data.tdesc, edesc: x.data.edesc, addressText: x.data.address, descOther: x.data.contact }))
} }
this.companyService.delete(body).subscribe({ this.companyService.delete(body).subscribe({
next: response => { next: response => {
...@@ -105,4 +114,73 @@ export class CompanyRegistrationPageComponent { ...@@ -105,4 +114,73 @@ export class CompanyRegistrationPageComponent {
}); });
} }
dataListCheckAll() {
const selectAll = this.isDataListCheckedAll;
this.dataList.filter(x => {
const data = x.data
const match = data.code.includes(this.search) || data.tdesc.includes(this.search) || data.edesc.includes(this.search);
return match;
}).forEach(x => x.check = selectAll);
this.dataListCheck();
}
dataListCheck() {
const dataCheck = this.dataListFilter();
this.isDataListCheckedAll = dataCheck.length ? dataCheck.every(x => x.check) : false;
this.numDataListChecked = this.dataList.filter(x => x.check).length;
this.isDataListChecked = Boolean(this.numDataListChecked)
}
onFileSelected(event: any) {
this.selectedFile = event.target.files.length > 0 ? event.target.files[0] : null;
this.selectedFileName = this.selectedFile?.name || "กรุณาเลือกไฟล์"
}
uploadFile() {
if (!this.selectedFile) {
alert('กรุณาเลือกไฟล์ก่อนอัปโหลด')
return
}
const formData = new FormData();
formData.append('file', this.selectedFile);
this.dataLoading = true
this.fileService.upload(formData, '').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getCompanyList()
} else {
this.showAlert(response.message, 'error')
this.dataLoading = false
this.cdr.detectChanges();
}
}, error: error => {
this.showAlert(error.message, 'error')
this.dataLoading = false
this.cdr.detectChanges();
}
})
}
downloadFile() {
const fileName = '.xlsx'
this.fileService.download(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
clearData() {
if (this.modalStatus == 'add') {
this.setData()
} else {
this.setData({ code: this.dataSelect.code, tdesc: "", edesc: "", address: "", contact: "" })
}
}
} }
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
</a> </a>
</nav> </nav>
</div> </div>
<div class="mt-3 px-3rem !-mt-3 pt-50px"> <div class="mt-3 px-2rem !-mt-3 pt-50px">
<div id="underline-1" role="tabpanel" aria-labelledby="underline-item-1"> <div id="underline-1" role="tabpanel" aria-labelledby="underline-item-1">
<app-sub-employee-registration></app-sub-employee-registration> <app-sub-employee-registration></app-sub-employee-registration>
</div> </div>
......
<div class="w-full min-height-50px mb-10px justify-between items-center"> <div class="w-full min-height-50px mb-10px justify-between items-center">
<div class="flex pr-2 pb-2rem">
<div class="flex">
<div class="flex items-center">
<input type="checkbox" class="ti-form-checkbox pointer-events-none" id="hs-default-checkbox"
[(ngModel)]="isDataListChecked">
<label for="hs-default-checkbox" class="text-sm text-gray-500 mx-2 pointer-events-none">
{{numDataListChecked}} Selected</label>
</div>
<div class="mx-1 flex items-center">
<button (click)="isDataListCheckedAll = !isDataListCheckedAll;dataListCheckAll()"
class="focus:ring-2 focus:ring-primary rounded-sm flex item-center">
<i class="fs-l transition-all duration-200"
[ngClass]="{'ri-checkbox-multiple-line text-gray-500': !isDataListCheckedAll, 'ri-checkbox-multiple-fill text-primary': isDataListCheckedAll}"></i>
</button>
<label class="text-sm text-gray-500 ml-2">Select All</label>
</div>
</div>
</div>
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex pr-2"> <div class="flex pr-2">
<div class="px-1"> <div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md" <button type="button" class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
data-hs-overlay="#sub-employee-registration-modal-upload"> data-hs-overlay="#sub-employee-registration-modal-upload"
(click)="fileInput.value = '';selectedFile=null;selectedFileName = 'กรุณาเลือกไฟล์'">
<i class="ri-add-line"></i> <i class="ri-add-line"></i>
นำเข้าข้อมูล นำเข้าข้อมูล
</button> </button>
<a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end" <a class="mx-2 justify-center -mb-px inline-flex items-center gap-2 font-weight-500 font-size-12px text-center text-secondary border-secondary border-b-2 align-items-end"
href="javascript:void(0);"> href="javascript:void(0);" (click)="downloadFile()">
ดาวน์โหลดตัวอย่างไฟล์ ดาวน์โหลดตัวอย่างไฟล์
</a> </a>
</div> </div>
...@@ -33,13 +52,21 @@ ...@@ -33,13 +52,21 @@
</button> </button>
</div> </div>
<div class="px-1"> <div class="px-1">
<button href="javascript:void(0);" class="ti-btn ti-btn-soft-info h-45px m-0 shadow-md"> <button class="ti-btn ti-btn-soft-danger h-45px m-0 shadow-md"
data-hs-overlay="#sub-employee-registration-alert-delete-modal"
(click)="modalType='deleteGroup';selectEmployee()">
<i class="ri-delete-bin-6-line"></i>
Delete
</button>
</div>
<div class="px-1">
<button class="ti-btn ti-btn-soft-info h-45px m-0 shadow-md">
<i class="ri-printer-line"></i> <i class="ri-printer-line"></i>
Print Print
</button> </button>
</div> </div>
<div class="px-1"> <div class="px-1">
<button href="javascript:void(0);" class="ti-btn ti-btn-soft-warning h-45px m-0 shadow-md"> <button class="ti-btn ti-btn-soft-warning h-45px m-0 shadow-md">
<i class="ti ti-book fs-l"></i> <i class="ti ti-book fs-l"></i>
Help Help
</button> </button>
...@@ -87,7 +114,7 @@ ...@@ -87,7 +114,7 @@
*ngFor="let item of employeeFilter() | slice:((currentPage-1) * 10) : (((currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of employeeFilter() | slice:((currentPage-1) * 10) : (((currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
<input type="checkbox" class="ti-form-checkbox cursor-pointer" id="checkbox-{{item.data.employeeId}}" <input type="checkbox" class="ti-form-checkbox cursor-pointer" id="checkbox-{{item.data.employeeId}}"
[(ngModel)]="item.check"> [(ngModel)]="item.check" (ngModelChange)="dataListCheck()">
<label for="checkbox-{{item.data.employeeId}}">&nbsp;{{item.data.employeeId}}</label> <label for="checkbox-{{item.data.employeeId}}">&nbsp;{{item.data.employeeId}}</label>
</td> </td>
<td>{{item.data.fname}}</td> <td>{{item.data.fname}}</td>
...@@ -357,17 +384,20 @@ ...@@ -357,17 +384,20 @@
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1> <h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2"> <div class="mt-2 p-2">
<div class="flex rounded-md"> <div class="flex rounded-md">
<input type="text" id="hs-trailing-button-add-on-with-icon" name="hs-trailing-button-add-on-with-icon" <input #fileInput id="fileInput" type="file" (change)="onFileSelected($event)" hidden>
class="ti-form-input rounded-none ltr:rounded-l-md rtl:rounded-r-md "> <input type="text" [value]="selectedFileName" readonly (click)="fileInput.click()"
<button aria-label="button" type="button" class="ti-form-input rounded-none ltr:rounded-l-md rtl:rounded-r-md focus:z-10 cursor-pointer">
class="inline-flex flex-shrink-0 justify-center items-center h-[2.875rem] w-[2.875rem] ltr:rounded-r-md rtl:rounded-l-md border border-transparent font-semibold bg-secondary text-white hover:bg-secondary focus:outline-none focus:ring-0 focus:ring-secondary transition-all text-sm"> <button type="button" (click)="fileInput.click()"
class="inline-flex flex-shrink-0 justify-center items-center h-[2.875rem] w-[2.875rem] ltr:rounded-r-md rtl:rounded-l-md border border-transparent font-semibold bg-secondary text-white hover:bg-secondary focus:z-10 focus:outline-none focus:ring-0 focus:ring-secondary transition-all text-sm">
<i class="ti ti-upload"></i> <i class="ti ti-upload"></i>
</button> </button>
</div> </div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4"> <div class="flex justify-center mt-2rem mb-1rem space-x-4">
<a class="ti-btn ti-btn-secondary" href="javascript:void(0);"> <button type="submit" class="ti-btn ti-btn-secondary" data-hs-overlay="#position-unit-component-upload-modal"
[class.ti-btn-disabled]="!selectedFile" (click)="uploadFile()" [disabled]="!selectedFile"
[disabled]="!selectedFile">
อัปโหลด อัปโหลด
</a> </button>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -12,6 +12,7 @@ import { Bu1Service } from 'src/app/shared/services/bu1.service'; ...@@ -12,6 +12,7 @@ import { Bu1Service } from 'src/app/shared/services/bu1.service';
import { EmpGroupService } from 'src/app/shared/services/emp-group.service'; import { EmpGroupService } from 'src/app/shared/services/emp-group.service';
import { EmpTypeService } from 'src/app/shared/services/employee-type.service'; import { EmpTypeService } from 'src/app/shared/services/employee-type.service';
import { EmployeeService } from 'src/app/shared/services/employee.service'; import { EmployeeService } from 'src/app/shared/services/employee.service';
import { FileService } from 'src/app/shared/services/file.service';
import { PLService } from 'src/app/shared/services/pl.service'; import { PLService } from 'src/app/shared/services/pl.service';
import { PositionService } from 'src/app/shared/services/position.service'; import { PositionService } from 'src/app/shared/services/position.service';
import { BranchService } from 'src/app/shared/services/่branch.service'; import { BranchService } from 'src/app/shared/services/่branch.service';
...@@ -41,7 +42,7 @@ export class SubEmployeeRegistrationComponent { ...@@ -41,7 +42,7 @@ export class SubEmployeeRegistrationComponent {
currentPage = 1 currentPage = 1
page = Array.from({ length: 1 }, (_, i) => i + 1); page = Array.from({ length: 1 }, (_, i) => i + 1);
search = "" search = ""
modalType: 'add' | 'update' | 'delete' = 'add' modalType: 'add' | 'update' | 'delete' | 'deleteGroup' = 'add'
modal: DataModal = { modal: DataModal = {
search: "", search: "",
...@@ -49,6 +50,13 @@ export class SubEmployeeRegistrationComponent { ...@@ -49,6 +50,13 @@ export class SubEmployeeRegistrationComponent {
page: Array.from({ length: 1 }, (_, i) => i + 1) page: Array.from({ length: 1 }, (_, i) => i + 1)
} }
numDataListChecked = 0
isDataListChecked = false
isDataListCheckedAll = false
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
empGroup: { loading: boolean, dataList: EmpGroupModel[] } = { loading: false, dataList: [] } empGroup: { loading: boolean, dataList: EmpGroupModel[] } = { loading: false, dataList: [] }
bu1: { loading: boolean, dataList: Bu1Model[] } = { loading: false, dataList: [] } bu1: { loading: boolean, dataList: Bu1Model[] } = { loading: false, dataList: [] }
position: { loading: boolean, dataList: PositionModel[] } = { loading: false, dataList: [] } position: { loading: boolean, dataList: PositionModel[] } = { loading: false, dataList: [] }
...@@ -65,6 +73,7 @@ export class SubEmployeeRegistrationComponent { ...@@ -65,6 +73,7 @@ export class SubEmployeeRegistrationComponent {
private jobcodeService: JobCodeService, private jobcodeService: JobCodeService,
private branchService: BranchService, private branchService: BranchService,
private empTypeService: EmpTypeService, private empTypeService: EmpTypeService,
private fileService: FileService,
private pLService: PLService) { } private pLService: PLService) { }
ngOnInit(): void { ngOnInit(): void {
...@@ -77,6 +86,53 @@ export class SubEmployeeRegistrationComponent { ...@@ -77,6 +86,53 @@ export class SubEmployeeRegistrationComponent {
this.getEmpTypeList() this.getEmpTypeList()
this.getPlList() this.getPlList()
} }
onFileSelected(event: any) {
this.selectedFile = event.target.files.length > 0 ? event.target.files[0] : null;
this.selectedFileName = this.selectedFile?.name || "กรุณาเลือกไฟล์"
}
uploadFile() {
if (!this.selectedFile) {
alert('กรุณาเลือกไฟล์ก่อนอัปโหลด')
return
}
const formData = new FormData();
formData.append('file', this.selectedFile);
this.employee.loading = true
this.fileService.upload(formData, '').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getEmployeeList()
} else {
this.showAlert(response.message, 'error')
this.employee.loading = false
this.cdr.detectChanges();
}
}, error: error => {
this.showAlert(error.message, 'error')
this.employee.loading = false
this.cdr.detectChanges();
}
})
}
downloadFile() {
const fileName = 'IMPORT_MPOSITION.xlsx'
this.fileService.download(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
getPlList() { getPlList() {
this.pl.loading = false this.pl.loading = false
this.pLService.getList().subscribe({ this.pLService.getList().subscribe({
...@@ -225,6 +281,8 @@ export class SubEmployeeRegistrationComponent { ...@@ -225,6 +281,8 @@ export class SubEmployeeRegistrationComponent {
next: response => { next: response => {
this.employee.dataList = response.map((x: any) => ({ check: false, data: new MyEmployeeModel(x) })) this.employee.dataList = response.map((x: any) => ({ check: false, data: new MyEmployeeModel(x) }))
this.employee.loading = false this.employee.loading = false
this.isDataListCheckedAll = false
this.dataListCheckAll()
this.searchChange() this.searchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => { }, error: error => {
...@@ -233,10 +291,18 @@ export class SubEmployeeRegistrationComponent { ...@@ -233,10 +291,18 @@ export class SubEmployeeRegistrationComponent {
} }
}) })
} }
updateEmployeeList(type: 'add' | 'update' | 'delete') { updateEmployeeList(type: 'add' | 'update' | 'delete' | 'deleteGroup') {
let body = this.employee.select let body = this.employee.select
if (type == 'delete') { switch (type) {
case 'delete': {
body = [this.employee.select] body = [this.employee.select]
break;
}
case 'deleteGroup': {
body = this.employee.dataList.filter(x => x.check).map(x => new MyEmployeeModel(x.data))
type = 'delete'
break;
}
} }
this.employeeService[type](body).subscribe({ this.employeeService[type](body).subscribe({
next: response => { next: response => {
...@@ -254,6 +320,7 @@ export class SubEmployeeRegistrationComponent { ...@@ -254,6 +320,7 @@ export class SubEmployeeRegistrationComponent {
searchChange() { searchChange() {
this.currentPage = 1 this.currentPage = 1
this.page = Array.from({ length: Math.ceil(this.employeeFilter().length / 10) }, (_, i) => i + 1); this.page = Array.from({ length: Math.ceil(this.employeeFilter().length / 10) }, (_, i) => i + 1);
this.dataListCheck()
} }
employeeFilter() { employeeFilter() {
return this.employee.dataList.filter(x => return this.employee.dataList.filter(x =>
...@@ -300,4 +367,22 @@ export class SubEmployeeRegistrationComponent { ...@@ -300,4 +367,22 @@ export class SubEmployeeRegistrationComponent {
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}) })
} }
dataListCheckAll() {
const selectAll = this.isDataListCheckedAll;
this.employee.dataList.filter(x =>
x.data.employeeId.toLowerCase().includes(this.search.toLowerCase()) ||
x.data.fname.toLowerCase().includes(this.search.toLowerCase()) ||
x.data.lname.toLowerCase().includes(this.search.toLowerCase()) ||
x.data.position.tdesc.toLowerCase().includes(this.search.toLowerCase()) ||
x.data.jobCode.tdesc.toLowerCase().includes(this.search.toLowerCase())).forEach(x => x.check = selectAll);
this.dataListCheck();
}
dataListCheck() {
const dataCheck = this.employeeFilter();
this.isDataListCheckedAll = dataCheck.length ? dataCheck.every(x => x.check) : false;
this.numDataListChecked = this.employee.dataList.filter(x => x.check).length;
this.isDataListChecked = Boolean(this.numDataListChecked)
}
} }
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
<div class="px-1"> <div class="px-1">
<div class="relative shadow-md"> <div class="relative shadow-md">
<input type="text" id="hs-leading-icon" name="hs-leading-icon" <input type="text" id="hs-leading-icon" name="hs-leading-icon"
class="ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 " placeholder="Search by No. or Name"> class="ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 " placeholder="Search by No. or Name"
[(ngModel)]="search" (ngModelChange)="searchEMP()">
<div <div
class="absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4"> class="absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4">
<i class="ri-search-line text-gray"></i> <i class="ri-search-line text-gray"></i>
...@@ -44,60 +45,73 @@ ...@@ -44,60 +45,73 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody> <tbody *ngIf="groupapprove_listLoading">
<tr *ngFor="let item of[ <tr>
['สุชาตา บาทวงษ์','อุทุมพร ประชาดี','พรเทพ ทองแย้ม','มัทนา ย่าล่า','',''], <td class="text-center" colspan="100%">
['ฐานปนีย์ สกุลวงษ์','อุทุมพร ประชาดี','พรเทพ ทองแย้ม','มัทนา ย่าล่า','',''], <div *ngFor="let item of [1,2,3]" class="ti-spinner w-8 h-8 text-secondary mx-1" role="status"
['วิครุฑ มานะดี','อุทุมพร ประชาดี','พรเทพ ทองแย้ม','','',''], aria-label="loading">
['สุมาลี รักษีสิงห์','อุทุมพร ประชาดี','ชุมพล น้อยพิทักษ์','','',''], <span class="sr-only">Loading...</span>
['กรวิภา ชัยสวัสดิ์','อุทุมพร ประชาดี','ชุมพล น้อยพิทักษ์','','',''], </div>
['กสินธร สีปัญญา','อุทุมพร ประชาดี','ชุมพล น้อยพิทักษ์','','','']];let i = index"> </td>
<td >{{item[0]}}</td> </tr>
<td >{{item[1]}}</td> </tbody>
<td >{{item[2]}}</td> <tbody *ngIf="!groupapprove_listLoading&&!groupapprove_listFilter().length">
<td >{{item[3]}}</td> <tr>
<td >{{item[4]}}</td> <td class="text-center" colspan="100%">
<td >{{item[5]}}</td> ไม่พบข้อมูล
</td>
</tr>
</tbody>
<tbody *ngIf="!groupapprove_listLoading&&groupapprove_listFilter().length">
<tr
*ngFor="let item of groupapprove_listFilter() | slice:((currentPage-1) * 10) : (((currentPage-1) * 10) + 10);let i = index">
<td>{{item.apsassessy.fname}} {{item.apsassessy.lname}}</td>
<td>{{item.apsapprove1.fname}} {{item.apsapprove1.lname}}</td>
<td>{{item.apsapprove2.fname}} {{item.apsapprove2.lname}}</td>
<td>{{item.apsapprove3.fname}} {{item.apsapprove3.lname}}</td>
<td>{{item.apsapprove4.fname}} {{item.apsapprove4.lname}}</td>
<td>{{item.apsapprove5.fname}} {{item.apsapprove5.lname}}</td>
<td class="flex justify-center"> <td class="flex justify-center">
<i class="ti ti-edit cursor-pointer i-gray fs-l px-1" <i class="ti ti-edit cursor-pointer i-gray fs-l px-1"
(click)="currentModel='edit';selectGroupapprove(item)"
data-hs-overlay="#set-approvers-modal-edit"></i> data-hs-overlay="#set-approvers-modal-edit"></i>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="body-content" style="margin-top: 20px;"> <nav class="pagination-style-3 overflow-auto my-5" *ngIf="page.length">
<ul class="nav-tabs">
<div class="px-1 py-1 bg-white rounded-2 shadow justify-content-center align-items-center">
<div class="box-body">
<nav class="pagination-style-3 overflow-auto">
<ul class="ti-pagination"> <ul class="ti-pagination">
<li> <li>
<a aria-label="anchor" class="page-link" href="javascript:void(0);"> <a aria-label="anchor" class="page-link" href="javascript:void(0);"
(click)="currentPage = (currentPage-1 || 1)">
<i class="ri-arrow-left-s-line align-middle rtl:rotate-180"></i> <i class="ri-arrow-left-s-line align-middle rtl:rotate-180"></i>
</a> </a>
</li> </li>
<li><a class="page-link active" href="javascript:void(0);" aria-current="page">1</a></li> <li *ngFor="let item of page;let f = first;let l = last">
<li><a class="page-link" href="javascript:void(0);">2</a></li> <ng-container *ngIf="item==3&&currentPage!=1&&currentPage!=2&&currentPage!=3">
<li><a class="page-link" href="javascript:void(0);">3</a></li> <a aria-label="anchor" class="page-link" href="javascript:void(0);"><i class="ri-more-line"></i>
<li><a class="page-link" href="javascript:void(0);">4</a></li> </a>
<li><a class="page-link" href="javascript:void(0);">5</a></li> </ng-container>
<li><a class="page-link" href="javascript:void(0);">...</a></li> <ng-container *ngIf="(f||l)||(item==currentPage-1||item==currentPage||item==currentPage+1)">
<li><a class="page-link" href="javascript:void(0);">31</a></li> <a class="page-link" href="javascript:void(0);" [class.active]="item==currentPage"
(click)="currentPage=item">{{item}}
</a>
</ng-container>
<ng-container
*ngIf="item==page.length-2&&currentPage!=page.length&&currentPage!=page.length-1&&currentPage!=page.length-2">
<a aria-label="anchor" class="page-link" href="javascript:void(0);"><i class="ri-more-line"></i>
</a>
</ng-container>
</li>
<li> <li>
<a aria-label="anchor" class="page-link" href="javascript:void(0);"> <a aria-label="anchor" class="page-link" href="javascript:void(0);"
(click)="currentPage = (currentPage > page.length-1 ? currentPage: currentPage+1 )">
<i class="ri-arrow-right-s-line align-middle rtl:rotate-180"></i> <i class="ri-arrow-right-s-line align-middle rtl:rotate-180"></i>
</a> </a>
</li> </li>
</ul> </ul>
</nav> </nav>
</div>
</div>
</ul>
<ul class="nav-tabs mt-1">
<p>Show 1 to 10 of 50 items</p>
</ul>
</div>
</div> </div>
...@@ -145,20 +159,25 @@ ...@@ -145,20 +159,25 @@
</div> </div>
</div> </div>
<div class="ti-modal-body mt-1"> <div class="ti-modal-body mt-1">
<label for="input-label" class="ti-form-label">ระดับพนักงาน</label> <label for="input-label" class="ti-form-label">ชื่อพนักงาน *</label>
<input type="text" id="input-label" class="ti-form-input w-1/2 bg-input-readonly" readonly
[value]="groupapprove.apsassessy.fname + ' ' + groupapprove.apsassessy.lname">
<label for="input-label" class="ti-form-label mt-2rem">ระดับพนักงาน</label>
<input type="text" id="input-label" class="ti-form-input w-1/2 bg-input-readonly" readonly <input type="text" id="input-label" class="ti-form-input w-1/2 bg-input-readonly" readonly
value="พนักงานระดับ 01-02"> [value]="groupapprove.personalLevel.tdesc">
<label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 1</label> <label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 1</label>
<div class="flex"> <div class="flex">
<div class="relative flex rounded-md w-2/3"> <div class="relative flex rounded-md w-2/3">
<input type="text" id="hs-leading-button-add-on-with-icon-and-button" <input type="text" name="hs-leading-button-add-on-with-icon-and-button"
name="hs-leading-button-add-on-with-icon-and-button" class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10 bg-input-readonly"
class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10" readonly style="padding-right: 2.5rem;" [(ngModel)]="groupapprove.apsapprove1.fname">
style="padding-right: 2.5rem;" value="">
<div <div
class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"> class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2">
<button type="button" class="flex items-center text-red-500" (click)="selectEMP()">
<i class="ti ti-circle-x cursor-pointer"></i>
</button>
<button type="button" class="flex items-center text-gray-500 dark:text-white/70" <button type="button" class="flex items-center text-gray-500 dark:text-white/70"
data-hs-overlay="#set-approvers-table-modal-edit"> (click)="empnumber = 1" data-hs-overlay="#set-approvers-table-modal-edit">
<i class="ri-search-line cursor-pointer text-gray"></i> <i class="ri-search-line cursor-pointer text-gray"></i>
</button> </button>
</div> </div>
...@@ -167,14 +186,16 @@ ...@@ -167,14 +186,16 @@
<label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 2</label> <label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 2</label>
<div class="flex"> <div class="flex">
<div class="relative flex rounded-md w-2/3"> <div class="relative flex rounded-md w-2/3">
<input type="text" id="hs-leading-button-add-on-with-icon-and-button" <input type="text" name="hs-leading-button-add-on-with-icon-and-button"
name="hs-leading-button-add-on-with-icon-and-button" class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10 bg-input-readonly"
class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10" readonly style="padding-right: 2.5rem;" [(ngModel)]="groupapprove.apsapprove2.fname">
style="padding-right: 2.5rem;" value="">
<div <div
class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"> class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2">
<button type="button" class="flex items-center text-red-500" (click)="selectEMP()">
<i class="ti ti-circle-x cursor-pointer"></i>
</button>
<button type="button" class="flex items-center text-gray-500 dark:text-white/70" <button type="button" class="flex items-center text-gray-500 dark:text-white/70"
data-hs-overlay="#set-approvers-table-modal-edit"> data-hs-overlay="#set-approvers-table-modal-edit" (click)="empnumber = 2">
<i class="ri-search-line cursor-pointer text-gray"></i> <i class="ri-search-line cursor-pointer text-gray"></i>
</button> </button>
</div> </div>
...@@ -183,14 +204,16 @@ ...@@ -183,14 +204,16 @@
<label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 3</label> <label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 3</label>
<div class="flex"> <div class="flex">
<div class="relative flex rounded-md w-2/3"> <div class="relative flex rounded-md w-2/3">
<input type="text" id="hs-leading-button-add-on-with-icon-and-button" <input type="text" name="hs-leading-button-add-on-with-icon-and-button"
name="hs-leading-button-add-on-with-icon-and-button" class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10 bg-input-readonly"
class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10" readonly style="padding-right: 2.5rem;" [(ngModel)]="groupapprove.apsapprove3.fname">
style="padding-right: 2.5rem;" value="">
<div <div
class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"> class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2">
<button type="button" class="flex items-center text-red-500">
<i class="ti ti-circle-x cursor-pointer"></i>
</button>
<button type="button" class="flex items-center text-gray-500 dark:text-white/70" <button type="button" class="flex items-center text-gray-500 dark:text-white/70"
data-hs-overlay="#set-approvers-table-modal-edit"> data-hs-overlay="#set-approvers-table-modal-edit" (click)="empnumber = 3">
<i class="ri-search-line cursor-pointer text-gray"></i> <i class="ri-search-line cursor-pointer text-gray"></i>
</button> </button>
</div> </div>
...@@ -199,14 +222,16 @@ ...@@ -199,14 +222,16 @@
<label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 4</label> <label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 4</label>
<div class="flex"> <div class="flex">
<div class="relative flex rounded-md w-2/3"> <div class="relative flex rounded-md w-2/3">
<input type="text" id="hs-leading-button-add-on-with-icon-and-button" <input type="text" name="hs-leading-button-add-on-with-icon-and-button"
name="hs-leading-button-add-on-with-icon-and-button" class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10 bg-input-readonly"
class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10" readonly style="padding-right: 2.5rem;" [(ngModel)]="groupapprove.apsapprove4.fname">
style="padding-right: 2.5rem;" value="">
<div <div
class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"> class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2">
<button type="button" class="flex items-center text-red-500">
<i class="ti ti-circle-x cursor-pointer"></i>
</button>
<button type="button" class="flex items-center text-gray-500 dark:text-white/70" <button type="button" class="flex items-center text-gray-500 dark:text-white/70"
data-hs-overlay="#set-approvers-table-modal-edit"> data-hs-overlay="#set-approvers-table-modal-edit" (click)="empnumber = 4">
<i class="ri-search-line cursor-pointer text-gray"></i> <i class="ri-search-line cursor-pointer text-gray"></i>
</button> </button>
</div> </div>
...@@ -215,14 +240,16 @@ ...@@ -215,14 +240,16 @@
<label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 5</label> <label class="ti-form-label mt-2rem">ผู้ประเมินลำดับที่ 5</label>
<div class="flex"> <div class="flex">
<div class="relative flex rounded-md w-2/3"> <div class="relative flex rounded-md w-2/3">
<input type="text" id="hs-leading-button-add-on-with-icon-and-button" <input type="text" name="hs-leading-button-add-on-with-icon-and-button"
name="hs-leading-button-add-on-with-icon-and-button" class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10 bg-input-readonly"
class="ti-form-input rounded-md ltr:rounded-r-md rtl:rounded-l-md focus:z-10" readonly style="padding-right: 2.5rem;" [(ngModel)]="groupapprove.apsapprove5.fname">
style="padding-right: 2.5rem;" value="">
<div <div
class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2"> class="absolute inset-y-0 ltr:right-0 rtl:left-0 flex items-center z-20 ltr:pr-4 rtl:pl-4 space-x-2">
<button type="button" class="flex items-center text-red-500">
<i class="ti ti-circle-x cursor-pointer"></i>
</button>
<button type="button" class="flex items-center text-gray-500 dark:text-white/70" <button type="button" class="flex items-center text-gray-500 dark:text-white/70"
data-hs-overlay="#set-approvers-table-modal-edit"> data-hs-overlay="#set-approvers-table-modal-edit" (click)="empnumber = 5">
<i class="ri-search-line cursor-pointer text-gray"></i> <i class="ri-search-line cursor-pointer text-gray"></i>
</button> </button>
</div> </div>
...@@ -264,8 +291,8 @@ ...@@ -264,8 +291,8 @@
<div class="px-1"> <div class="px-1">
<div class="relative shadow-md"> <div class="relative shadow-md">
<input type="text" id="hs-leading-icon" name="hs-leading-icon" <input type="text" id="hs-leading-icon" name="hs-leading-icon"
class="ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 " class="ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 " placeholder="Search by No. or Name"
placeholder="Search by No. or Name"> [(ngModel)]="search" (ngModelChange)="searchChange()">
<div <div
class="absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4"> class="absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4">
<i class="ri-search-line text-gray"></i> <i class="ri-search-line text-gray"></i>
...@@ -311,27 +338,30 @@ ...@@ -311,27 +338,30 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody> <tbody *ngIf="!employee_listFilter().length">
<tr <tr>
*ngFor="let item of[ <td class="text-center" colspan="100%">
['10001', 'สามารถ','พยัคร้าย','Human Resource Development Officer','BU5'], ไม่พบข้อมูล
['10002', 'สมหวัง','ฟันหลุด','Human Resource Development Officer','BU5'], </td>
['10003', 'สามารถ','พยัคร้าย','Human Resource Development Officer','BU5'], </tr>
['10004', 'สมหวัง','ฟันหลุด','Human Resource Development Officer','BU5'], </tbody>
['10005', 'สามารถ','พยัคร้าย','Human Resource Development Officer','BU5'], <tbody *ngIf="employee_listFilter().length">
['10006', 'สมจิต','ฟันหลอ','Human Resource Development Officer','BU5'],];let i = index"> <ng-container *ngIf="currentModel=='edit'">
<td class="flex justify-center" style="font-size: 12px;">{{item[0]}}</td> <tr *ngFor="let item of employee_listFilter() | slice:((employeeModal.currentPage-1) * 10) : (((employeeModal.currentPage-1) * 10) + 10);let i = index"
<td style="font-size: 12px; width: 20%;">{{item[1]}}</td> class="cursor-pointer">
<td style="font-size: 12px; width: 20%;">{{item[2]}}</td> <td style="font-size: 12px;">{{item.employeeId}}</td>
<td style="font-size: 12px; width: 20%;">{{item.fname}}</td>
<td style="font-size: 12px; width: 20%;">{{item.lname}}</td>
<td <td
style="font-size: 12px; width: 20%; word-break: break-word; white-space: normal;"> style="font-size: 12px; width: 20%; word-break: break-word; white-space: normal;">
{{item[3]}} {{item.position.tdesc}}
</td> </td>
<td style="font-size: 12px; width: 20%;">{{item[4]}}</td> <td style="font-size: 12px; width: 10%;">{{item.bu1.bu1id}}</td>
<td class="flex justify-center"> <td class="flex justify-center">
<div class="px-1"> <div class="px-1">
<button type="button" <button type="button"
class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md" class="ti-btn ti-btn-soft-secondary h-20px m-0 shadow-md"
(click)="selectEMP(item)"
data-hs-overlay="#set-approvers-modal-edit"> data-hs-overlay="#set-approvers-modal-edit">
<i class="ri-add-line"></i> <i class="ri-add-line"></i>
Select Select
...@@ -339,31 +369,28 @@ ...@@ -339,31 +369,28 @@
</div> </div>
</td> </td>
</tr> </tr>
</ng-container>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
<div class="body-content" style="margin-top: 20px;"> <nav class="pagination-style-3 overflow-auto my-5" *ngIf="employeeModal.page.length">
<ul class="nav-tabs">
<div class="px-1 bg-white rounded-2 shadow justify-content-center align-items-center">
<div class="box-body">
<nav class="pagination-style-3 overflow-auto">
<ul class="ti-pagination"> <ul class="ti-pagination">
<li> <li>
<a aria-label="anchor" class="page-link" href="javascript:void(0);"> <a aria-label="anchor" class="page-link" href="javascript:void(0);"
(click)="employeeModal.currentPage = (employeeModal.currentPage-1 || 1)">
<i class="ri-arrow-left-s-line align-middle rtl:rotate-180"></i> <i class="ri-arrow-left-s-line align-middle rtl:rotate-180"></i>
</a> </a>
</li> </li>
<li><a class="page-link active" href="javascript:void(0);" <li *ngFor="let item of employeeModal.page">
aria-current="page">1</a></li> <a class="page-link" href="javascript:void(0);"
<li><a class="page-link" href="javascript:void(0);">2</a></li> [class.active]="item==employeeModal.currentPage"
<li><a class="page-link" href="javascript:void(0);">3</a></li> (click)="employeeModal.currentPage=item">{{item}}
<li><a class="page-link" href="javascript:void(0);">4</a></li> </a>
<li><a class="page-link" href="javascript:void(0);">5</a></li> </li>
<li><a class="page-link" href="javascript:void(0);">...</a></li>
<li><a class="page-link" href="javascript:void(0);">31</a></li>
<li> <li>
<a aria-label="anchor" class="page-link" href="javascript:void(0);"> <a aria-label="anchor" class="page-link" href="javascript:void(0);"
(click)="employeeModal.currentPage = (employeeModal.currentPage > employeeModal.page.length-1 ? employeeModal.currentPage: employeeModal.currentPage+1 )">
<i class="ri-arrow-right-s-line align-middle rtl:rotate-180"></i> <i class="ri-arrow-right-s-line align-middle rtl:rotate-180"></i>
</a> </a>
</li> </li>
...@@ -371,13 +398,6 @@ ...@@ -371,13 +398,6 @@
</nav> </nav>
</div> </div>
</div> </div>
</ul>
<ul class="nav-tabs mt-1">
<p>Show 1 to 10 of 50 items</p>
</ul>
</div>
</div>
</div>
</div> </div>
</div> </div>
...@@ -408,7 +428,7 @@ ...@@ -408,7 +428,7 @@
ย้อนกลับ ย้อนกลับ
</button> </button>
<a class="ti-btn ti-btn-success" href="javascript:void(0);" <a class="ti-btn ti-btn-success" href="javascript:void(0);"
data-hs-overlay="#set-approvers-alert-edit-modal" (click)="addUser();showSuccessEdit()"> data-hs-overlay="#set-approvers-alert-edit-modal" (click)="addgroupapprove();showSuccessEdit()">
บันทึกข้อมูล บันทึกข้อมูล
</a> </a>
</div> </div>
......
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { EmployeeModel, MyEmployeeModel } from 'src/app/shared/model/employee.model';
import { GroupApproveModel, MyGroupApproveModel } from 'src/app/shared/model/group-approve.model';
import { EmployeeService } from 'src/app/shared/services/employee.service';
import { GroupApproveService } from 'src/app/shared/services/group-approve.service';
interface table {
currentPage: number,
page: number[],
search: string
}
@Component({ @Component({
selector: 'app-set-approvers', selector: 'app-set-approvers',
...@@ -9,77 +18,153 @@ import { ToastrService } from 'ngx-toastr'; ...@@ -9,77 +18,153 @@ import { ToastrService } from 'ngx-toastr';
export class SetApproversComponent { export class SetApproversComponent {
@Input() pathTitle = ['การประเมินจัดประเมินสมรรถนะ', 'การจัดการสมรรถนะ', 'กำหนดผู้ประเมิน']; @Input() pathTitle = ['การประเมินจัดประเมินสมรรถนะ', 'การจัดการสมรรถนะ', 'กำหนดผู้ประเมิน'];
@Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>(); @Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>();
activeTab: string = 'tab1'; // กำหนด tab เริ่มต้น activeTab: string = 'tab1';
// ฟังก์ชันในการเปลี่ยนแท็บ
changeTab(tab: { id: string, text: string }) { changeTab(tab: { id: string, text: string }) {
this.sendPathTitle.emit(['การสมรรถนะจัดประเมินสมรรถนะ', 'การจัดการประเมิน', tab.text]); this.sendPathTitle.emit(['การสมรรถนะจัดประเมินสมรรถนะ', 'การจัดการประเมิน', tab.text]);
this.activeTab = tab.id; this.activeTab = tab.id;
} }
// การจัดการการเปิดปิด modal currentPage = 1
modalOptions: { page = Array.from({ length: 1 }, (_, i) => i + 1);
[nameModal: string]: { groupapprove_list: GroupApproveModel[] = []
isModalOpen: boolean; groupapprove_listLoading = false
modalSize: string; groupapprove: GroupApproveModel = new MyGroupApproveModel()
backdropClose: boolean; search = ""
};
} = { employee_list: EmployeeModel[] = []
"add": { employee_listLoading = false
isModalOpen: false, employee: EmployeeModel = new MyEmployeeModel({})
modalSize: 'm', employeeModal: table = {
backdropClose: true, currentPage: 1,
}, page: Array.from({ length: 1 }, (_, i) => i + 1),
"edit": { search: ""
isModalOpen: false, }
modalSize: 'm', empnumber = 0
backdropClose: true,
} currentModel: 'add' | 'edit' | 'delete' = "add"
}; constructor(private groupapproveService: GroupApproveService,
private toastr: ToastrService,
openModal(name: string, size: string, closeOnBackdrop?: boolean) { private cdr: ChangeDetectorRef,
this.modalOptions[name].modalSize = size; private employeeService: EmployeeService,
this.modalOptions[name].backdropClose = closeOnBackdrop || false; ) { }
this.modalOptions[name].isModalOpen = true; ngOnInit(): void {
this.currentModal = name; // ตั้งค่าค่าของ currentModal เป็น 'add' หรือ 'edit' this.getGroupapprove_list()
document.body.style.overflow = 'hidden'; this.getEemployeeList()
} }
closeModal(name: string) { getEemployeeList() {
this.modalOptions[name].isModalOpen = false; this.employee_listLoading = true
if (!this.isAnyModalOpen()) { this.employeeService.getList().subscribe({
document.body.style.overflow = ''; // คืนค่าการ Scroll เฉพาะเมื่อ Modal ทั้งหมดปิดแล้ว next: response => {
this.employee_list = response.map(x => {
return new MyEmployeeModel(x)
})
this.employee_listLoading = false
this.searchEMP()
this.cdr.detectChanges()
}, error: error => {
this.employee_listLoading = false
this.cdr.detectChanges()
} }
})
} }
employee_listFilter() {
isAnyModalOpen(): boolean { return this.employee_list.filter(x => x.fname.toLowerCase().includes(this.search.toLowerCase()) ||
return Object.values(this.modalOptions).some(modal => modal.isModalOpen); // ตรวจสอบว่า modal อื่นยังเปิดอยู่หรือไม่ x.lname.toLowerCase().includes(this.search.toLowerCase()))
} }
searchEMP() {
// ฟังก์ชัน toggle checkbox this.employeeModal.currentPage = 1
isChecked: boolean = false; // ใช้สำหรับตรวจสอบสถานะของ checkbox this.employeeModal.page = Array.from({ length: Math.ceil(this.employee_listFilter().length / 10) }, (_, i) => i + 1);
toggleCheckbox() {
this.isChecked = !this.isChecked; // สลับสถานะ
} }
empChange() {
// ฟังก์ชันสำหรับการเพิ่ม ลบ หรือแก้ไข ข้อมูล const employee = this.employee_list.find(x => x.employeeId == this.employee.employeeId)
addUser() { this.selectEMP(employee || new MyEmployeeModel({ employeeId: this.employee.employeeId }))
console.log('เพิ่มผู้ใช้งาน');
} }
selectEMP(employee?: EmployeeModel) {
deleteUser() { const data = new MyEmployeeModel(employee || {});
console.log('ลบผู้ใช้งาน'); if (this.empnumber == 1) {
this.groupapprove.apsapprove1 = data
} else if (this.empnumber == 2) {
this.groupapprove.apsapprove2 = data
} else if (this.empnumber == 3) {
this.groupapprove.apsapprove3 = data
} else if (this.empnumber == 4) {
this.groupapprove.apsapprove4 = data
} else if (this.empnumber == 5) {
this.groupapprove.apsapprove5 = data
} }
editUser() { }
console.log('แก้ไขผู้ใช้งาน'); getGroupapprove_list() {
this.groupapprove_listLoading = true
this.groupapproveService.getList().subscribe({
next: response => {
this.groupapprove_list = response.map(x => new MyGroupApproveModel(x))
this.groupapprove_listLoading = false
this.searchChange()
this.cdr.detectChanges()
}, error: error => {
this.groupapprove_listLoading = false
this.cdr.detectChanges()
}
})
}
searchChange() {
this.currentPage = 1
this.page = Array.from({ length: Math.ceil(this.groupapprove_listFilter().length / 10) }, (_, i) => i + 1);
}
groupapprove_listFilter() {
return this.groupapprove_list.filter(x => x.apsapprove1.employeeId||x.apsapprove2.employeeId||x.apsapprove3.employeeId||x.apsapprove4.employeeId||x.apsapprove5.employeeId.toLowerCase().includes(this.search.toLowerCase()) ||
x.apsapprove1.fname || x.apsapprove1.lname.toLowerCase().includes(this.search.toLowerCase()) ||
x.apsapprove2.fname || x.apsapprove2.lname.toLowerCase().includes(this.search.toLowerCase()) ||
x.apsapprove3.fname || x.apsapprove3.lname.toLowerCase().includes(this.search.toLowerCase()) ||
x.apsapprove4.fname || x.apsapprove4.lname.toLowerCase().includes(this.search.toLowerCase()) ||
x.apsapprove5.fname || x.apsapprove5.lname.toLowerCase().includes(this.search.toLowerCase()))
} }
currentModal = ""; selectGroupapprove(groupapprove?: GroupApproveModel) {
this.groupapprove = new MyGroupApproveModel(groupapprove)
}
constructor(private toastr: ToastrService) { } showAlert(text: string, type: 'success' | 'error') {
this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
})
}
addgroupapprove() {
this.groupapprove_listLoading = true
this.groupapproveService.post(this.groupapprove).subscribe({
next: response => {
if (response.success) {
this.getGroupapprove_list()
} else {
this.showAlert(response.message, 'error')
this.groupapprove_listLoading = false
}
}, error: error => {
this.showAlert(error.message, 'error')
this.groupapprove_listLoading = false
}
})
}
deletegroupapprove() {
this.groupapprove_listLoading = true
this.groupapproveService.delete(this.groupapprove).subscribe({
next: response => {
if (response.success) {
this.getGroupapprove_list()
} else {
this.showAlert(response.message, 'error')
this.groupapprove_listLoading = false
}
}, error: error => {
this.showAlert(error.message, 'error')
this.groupapprove_listLoading = false
}
})
}
showSuccess() { showSuccess() {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', {
......
...@@ -134,6 +134,7 @@ import { FileService } from 'src/app/shared/services/file.service'; ...@@ -134,6 +134,7 @@ import { FileService } from 'src/app/shared/services/file.service';
import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service'; import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service';
import { IndicatorsCoursesService } from 'src/app/shared/services/indicators-courses.service'; import { IndicatorsCoursesService } from 'src/app/shared/services/indicators-courses.service';
import { IdpDevelopmentService } from 'src/app/shared/services/idp-development.service'; import { IdpDevelopmentService } from 'src/app/shared/services/idp-development.service';
import { GroupApproveService } from 'src/app/shared/services/group-approve.service';
import { UserService } from 'src/app/shared/services/user.service'; import { UserService } from 'src/app/shared/services/user.service';
import { ManageUserComponent } from '../company-components/account-settings/manage-user/manage-user.component'; import { ManageUserComponent } from '../company-components/account-settings/manage-user/manage-user.component';
...@@ -301,6 +302,7 @@ export class CustomDateAdapter extends NativeDateAdapter { ...@@ -301,6 +302,7 @@ export class CustomDateAdapter extends NativeDateAdapter {
CompetencyGroupGradeService, CompetencyGroupGradeService,
IndicatorsCoursesService, IndicatorsCoursesService,
IdpDevelopmentService, IdpDevelopmentService,
GroupApproveService,
UserService, UserService,
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
......
import { EmployeeModel, MyEmployeeModel } from "./employee.model";
import { MyPLModel, PLModel } from "./pl.model";
export interface GroupApproveModel {
personalLevel: PLModel;
apsassessy: EmployeeModel;
companyId: string;
apsapprove1: EmployeeModel;
apsapprove2: EmployeeModel;
apsapprove3: EmployeeModel;
apsapprove4: EmployeeModel;
apsapprove5: EmployeeModel;
}
export class MyGroupApproveModel implements GroupApproveModel {
personalLevel: PLModel;
apsassessy: EmployeeModel
companyId: string;
apsapprove1: EmployeeModel;
apsapprove2: EmployeeModel;
apsapprove3: EmployeeModel;
apsapprove4: EmployeeModel;
apsapprove5: EmployeeModel;
constructor(data: Partial<GroupApproveModel> = {}) {
this.personalLevel = new MyPLModel(data.personalLevel || {});
this.apsassessy = new MyEmployeeModel(data.apsassessy || {})
this.companyId = data.companyId || '';
this.apsapprove1 = new MyEmployeeModel(data.apsapprove1 || {});
this.apsapprove2 = new MyEmployeeModel(data.apsapprove2 || {});
this.apsapprove3 = new MyEmployeeModel(data.apsapprove3 || {});
this.apsapprove4 = new MyEmployeeModel(data.apsapprove4 || {});
this.apsapprove5 = new MyEmployeeModel(data.apsapprove5 || {});
}
}
\ No newline at end of file
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { GroupApproveModel } from '../model/group-approve.model';
import { AlertModel } from '../model/alert.model';
@Injectable({
providedIn: 'root'
})
export class GroupApproveService {
api = "/group-approve"
urlApi = environment.baseUrl + this.api
constructor(private http: HttpClient) {
}
getByPersonalLevel(plId: string): Observable<GroupApproveModel> {
return this.http.get<GroupApproveModel>(this.urlApi + "/" + plId);
}
getList(): Observable<GroupApproveModel[]> {
return this.http.get<GroupApproveModel[]>(this.urlApi + "/lists")
}
post(body: GroupApproveModel): Observable<AlertModel> {
return this.http.post<AlertModel>(this.urlApi, body)
}
delete(body: GroupApproveModel) : Observable<AlertModel> {
const options = {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
body: body
};
return this.http.delete<AlertModel>(this.urlApi, options)
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment