Commit 0d09ca12 by LAPTOP-CV4JFSHE\kantavee

เเก้ชน

parents 1abde7ec 08eb44ff
...@@ -3,12 +3,13 @@ ...@@ -3,12 +3,13 @@
<div class="flex pr-2"> <div class="flex pr-2">
<!-- Content ของ div แรก --> <!-- Content ของ div แรก -->
<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="#department-list-upload-modal">
<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>
...@@ -65,14 +66,24 @@ ...@@ -65,14 +66,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu2Table().length"> <tbody *ngIf="bu2ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu2ListLoading&&!filterBu2Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu2Table().length"> <tbody *ngIf="!bu2ListLoading&&filterBu2Table().length">
<tr <tr
*ngFor="let item of filterBu2Table() | slice:((bu2Table.currentPage-1) * 10) : (((bu2Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu2Table() | slice:((bu2Table.currentPage-1) * 10) : (((bu2Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -664,3 +675,33 @@ ...@@ -664,3 +675,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="department-list-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนแผนก
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu1Model, MyBu1Model } from 'src/app/shared/model/bu1.model'; ...@@ -4,6 +4,7 @@ import { Bu1Model, MyBu1Model } from 'src/app/shared/model/bu1.model';
import { Bu2Model, MyBu2Model } from 'src/app/shared/model/bu2.model'; import { Bu2Model, MyBu2Model } from 'src/app/shared/model/bu2.model';
import { Bu1Service } from 'src/app/shared/services/bu1.service'; import { Bu1Service } from 'src/app/shared/services/bu1.service';
import { Bu2Service } from 'src/app/shared/services/bu2.service'; import { Bu2Service } from 'src/app/shared/services/bu2.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
page: number[], page: number[],
...@@ -16,12 +17,17 @@ interface table { ...@@ -16,12 +17,17 @@ interface table {
}) })
export class DepartmentListComponent implements OnInit { export class DepartmentListComponent implements OnInit {
bu2List: Bu2Model[] = [] bu2List: Bu2Model[] = []
bu2ListLoading = false
bu2: Bu2Model = new MyBu2Model({}) bu2: Bu2Model = new MyBu2Model({})
bu2Table: table = { bu2Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu2Modal: table = { bu2Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -38,17 +44,71 @@ export class DepartmentListComponent implements OnInit { ...@@ -38,17 +44,71 @@ export class DepartmentListComponent implements OnInit {
constructor(private bu2Service: Bu2Service, constructor(private bu2Service: Bu2Service,
private bu1Service: Bu1Service, private bu1Service: Bu1Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu2List() this.getBu2List()
this.getBu1List() this.getBu1List()
} }
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.fileService.upload(formData, 'mbu2').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu2List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu2List() { getBu2List() {
this.bu2Service.getList().subscribe(response => { this.bu2ListLoading = true
this.bu2Service.getList().subscribe({
next: response => {
this.bu2List = response this.bu2List = response
this.bu2ListLoading = false
this.onBu2TableSearchChange() this.onBu2TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu2ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu2TableSearchChange() { onBu2TableSearchChange() {
...@@ -56,9 +116,9 @@ export class DepartmentListComponent implements OnInit { ...@@ -56,9 +116,9 @@ export class DepartmentListComponent implements OnInit {
this.bu2Table.page = Array.from({ length: Math.ceil(this.filterBu2Table().length / 10) }, (_, i) => i + 1); this.bu2Table.page = Array.from({ length: Math.ceil(this.filterBu2Table().length / 10) }, (_, i) => i + 1);
} }
filterBu2Table() { filterBu2Table() {
return this.bu2List.filter(x => x.bu2id.includes(this.bu2Table.search) || return this.bu2List.filter(x => x.bu2id.toLowerCase().includes(this.bu2Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu2Table.search) || x.tdesc.toLowerCase().includes(this.bu2Table.search.toLowerCase()) ||
x.edesc.includes(this.bu2Table.search)) x.edesc.toLowerCase().includes(this.bu2Table.search.toLowerCase()))
} }
selectBu2(bu2?: Bu2Model) { selectBu2(bu2?: Bu2Model) {
this.bu2 = new MyBu2Model(bu2 || {}) this.bu2 = new MyBu2Model(bu2 || {})
...@@ -79,9 +139,9 @@ export class DepartmentListComponent implements OnInit { ...@@ -79,9 +139,9 @@ export class DepartmentListComponent implements OnInit {
this.bu2Modal.page = Array.from({ length: Math.ceil(this.filterBu2Modal().length / 10) }, (_, i) => i + 1); this.bu2Modal.page = Array.from({ length: Math.ceil(this.filterBu2Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu2Modal() { filterBu2Modal() {
return this.bu2List.filter(x => x.bu2id.includes(this.bu2Modal.search) || return this.bu2List.filter(x => x.bu2id.toLowerCase().includes(this.bu2Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu2Modal.search) || x.tdesc.toLowerCase().includes(this.bu2Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu2Modal.search)) x.edesc.toLowerCase().includes(this.bu2Modal.search.toLowerCase()))
} }
...@@ -100,45 +160,45 @@ export class DepartmentListComponent implements OnInit { ...@@ -100,45 +160,45 @@ export class DepartmentListComponent implements OnInit {
this.selectBu1(bu1 || new MyBu1Model({ bu1id: this.bu1.bu1id })) this.selectBu1(bu1 || new MyBu1Model({ bu1id: this.bu1.bu1id }))
} }
filterBu1Modal() { filterBu1Modal() {
return this.bu1List.filter(x => x.bu1id.includes(this.bu1Modal.search) || return this.bu1List.filter(x => x.bu1id.toLowerCase().includes(this.bu1Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu1Modal.search) || x.tdesc.toLowerCase().includes(this.bu1Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu1Modal.search)) x.edesc.toLowerCase().includes(this.bu1Modal.search.toLowerCase()))
} }
selectBu1(bu1?: Bu1Model) { selectBu1(bu1?: Bu1Model) {
this.bu1 = new MyBu1Model(bu1 || {}) this.bu1 = new MyBu1Model(bu1 || {})
} }
showSuccess() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
} }
addBu2() { addBu2() {
this.bu2Service.post({ ...this.bu2, parent: this.bu1.bu1id }).subscribe((response: any) => { this.bu2Service.post({ ...this.bu2, parent: this.bu1.bu1id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showSuccess() this.showAlert(response.message, 'success')
this.getBu2List() this.getBu2List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu2() { deleteBu2() {
this.bu2Service.delete(this.bu2).subscribe((response: any) => { this.bu2Service.delete(this.bu2).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showSuccessDelete() this.showAlert(response.message, 'success')
this.getBu2List() this.getBu2List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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="#department-register-upload-modal">
<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>
...@@ -334,3 +335,33 @@ ...@@ -334,3 +335,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="department-register-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนฝ่าย
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, } from '@ang ...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, } from '@ang
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { Bu1Model, MyBu1Model } from 'src/app/shared/model/bu1.model'; import { Bu1Model, MyBu1Model } from 'src/app/shared/model/bu1.model';
import { Bu1Service } from 'src/app/shared/services/bu1.service'; import { Bu1Service } from 'src/app/shared/services/bu1.service';
import { FileService } from 'src/app/shared/services/file.service';
@Component({ @Component({
selector: 'app-department-register', selector: 'app-department-register',
...@@ -15,13 +16,63 @@ export class DepartmentRegisterComponent implements OnInit { ...@@ -15,13 +16,63 @@ export class DepartmentRegisterComponent implements OnInit {
bu1ListLoading = false bu1ListLoading = false
bu1: Bu1Model = new MyBu1Model({}) bu1: Bu1Model = new MyBu1Model({})
search = "" search = ""
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
constructor(private bu1Service: Bu1Service, constructor(private bu1Service: Bu1Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu1List() this.getBu1List()
} }
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.fileService.upload(formData, 'mbu1').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu1List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu1List() { getBu1List() {
this.bu1ListLoading = true this.bu1ListLoading = true
this.bu1Service.getList().subscribe({ this.bu1Service.getList().subscribe({
...@@ -41,39 +92,45 @@ export class DepartmentRegisterComponent implements OnInit { ...@@ -41,39 +92,45 @@ export class DepartmentRegisterComponent implements OnInit {
this.page = Array.from({ length: Math.ceil(this.bu1ListFilter().length / 10) }, (_, i) => i + 1); this.page = Array.from({ length: Math.ceil(this.bu1ListFilter().length / 10) }, (_, i) => i + 1);
} }
bu1ListFilter() { bu1ListFilter() {
return this.bu1List.filter(x => x.bu1id.includes(this.search) || return this.bu1List.filter(x => x.bu1id.toLowerCase().includes(this.search.toLowerCase()) ||
x.tdesc.includes(this.search) || x.tdesc.toLowerCase().includes(this.search.toLowerCase()) ||
x.edesc.includes(this.search)) x.edesc.toLowerCase().includes(this.search.toLowerCase()))
} }
selectBu1(bu1?: Bu1Model) { selectBu1(bu1?: Bu1Model) {
this.bu1 = new MyBu1Model(bu1 || {}) this.bu1 = new MyBu1Model(bu1 || {})
} }
showSuccessAdd() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'แจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
} }
addBu1() { addBu1() {
this.bu1Service.post(this.bu1).subscribe((response: any) => { this.bu1Service.post(this.bu1).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showSuccessAdd() this.showAlert(response.message, 'success')
this.getBu1List() this.getBu1List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu1() { deleteBu1() {
this.bu1Service.delete(this.bu1).subscribe((response: any) => { this.bu1Service.delete(this.bu1).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showSuccessDelete() this.showAlert(response.message, 'success')
this.getBu1List() this.getBu1List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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="#section-registration-upload-modal">
<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>
...@@ -65,14 +66,24 @@ ...@@ -65,14 +66,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu3Table().length"> <tbody *ngIf="bu3ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu3ListLoading&&!filterBu3Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu3Table().length"> <tbody *ngIf="!bu3ListLoading&&filterBu3Table().length">
<tr <tr
*ngFor="let item of filterBu3Table() | slice:((bu3Table.currentPage-1) * 10) : (((bu3Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu3Table() | slice:((bu3Table.currentPage-1) * 10) : (((bu3Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -665,3 +676,33 @@ ...@@ -665,3 +676,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="section-registration-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนส่วน
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu2Model, MyBu2Model } from 'src/app/shared/model/bu2.model'; ...@@ -4,6 +4,7 @@ import { Bu2Model, MyBu2Model } from 'src/app/shared/model/bu2.model';
import { Bu3Model, MyBu3Model } from 'src/app/shared/model/bu3.model'; import { Bu3Model, MyBu3Model } from 'src/app/shared/model/bu3.model';
import { Bu2Service } from 'src/app/shared/services/bu2.service'; import { Bu2Service } from 'src/app/shared/services/bu2.service';
import { Bu3Service } from 'src/app/shared/services/bu3.service'; import { Bu3Service } from 'src/app/shared/services/bu3.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
page: number[], page: number[],
...@@ -16,12 +17,17 @@ interface table { ...@@ -16,12 +17,17 @@ interface table {
}) })
export class SectionRegistrationComponent implements OnInit { export class SectionRegistrationComponent implements OnInit {
bu3List: Bu3Model[] = [] bu3List: Bu3Model[] = []
bu3ListLoading = false
bu3: Bu3Model = new MyBu3Model({}) bu3: Bu3Model = new MyBu3Model({})
bu3Table: table = { bu3Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu3Modal: table = { bu3Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -38,17 +44,72 @@ export class SectionRegistrationComponent implements OnInit { ...@@ -38,17 +44,72 @@ export class SectionRegistrationComponent implements OnInit {
constructor(private bu3Service: Bu3Service, constructor(private bu3Service: Bu3Service,
private bu2Service: Bu2Service, private bu2Service: Bu2Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu3List() this.getBu3List()
this.getBu2List() this.getBu2List()
} }
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.fileService.upload(formData, 'mbu3').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu3List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu3List() { getBu3List() {
this.bu3Service.getList().subscribe(response => { this.bu3ListLoading = true
this.bu3Service.getList().subscribe({
next: response => {
this.bu3List = response this.bu3List = response
this.bu3ListLoading = false
this.onBu3TableSearchChange() this.onBu3TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu3ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu3TableSearchChange() { onBu3TableSearchChange() {
...@@ -56,9 +117,9 @@ export class SectionRegistrationComponent implements OnInit { ...@@ -56,9 +117,9 @@ export class SectionRegistrationComponent implements OnInit {
this.bu3Table.page = Array.from({ length: Math.ceil(this.filterBu3Table().length / 10) }, (_, i) => i + 1); this.bu3Table.page = Array.from({ length: Math.ceil(this.filterBu3Table().length / 10) }, (_, i) => i + 1);
} }
filterBu3Table() { filterBu3Table() {
return this.bu3List.filter(x => x.bu3id.includes(this.bu3Table.search) || return this.bu3List.filter(x => x.bu3id.toLowerCase().includes(this.bu3Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu3Table.search) || x.tdesc.toLowerCase().includes(this.bu3Table.search.toLowerCase()) ||
x.edesc.includes(this.bu3Table.search)) x.edesc.toLowerCase().includes(this.bu3Table.search.toLowerCase()))
} }
selectBu3(bu3?: Bu3Model) { selectBu3(bu3?: Bu3Model) {
this.bu3 = new MyBu3Model(bu3 || {}) this.bu3 = new MyBu3Model(bu3 || {})
...@@ -79,23 +140,35 @@ export class SectionRegistrationComponent implements OnInit { ...@@ -79,23 +140,35 @@ export class SectionRegistrationComponent implements OnInit {
this.bu3Modal.page = Array.from({ length: Math.ceil(this.filterBu3Modal().length / 10) }, (_, i) => i + 1); this.bu3Modal.page = Array.from({ length: Math.ceil(this.filterBu3Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu3Modal() { filterBu3Modal() {
return this.bu3List.filter(x => x.bu3id.includes(this.bu3Modal.search) || return this.bu3List.filter(x => x.bu3id.toLowerCase().includes(this.bu3Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu3Modal.search) || x.tdesc.toLowerCase().includes(this.bu3Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu3Modal.search)) x.edesc.toLowerCase().includes(this.bu3Modal.search.toLowerCase()))
} }
addBu3() { addBu3() {
this.bu3Service.post({ ...this.bu3, parent: this.bu2.bu2id }).subscribe((response:any) => { this.bu3Service.post({ ...this.bu3, parent: this.bu2.bu2id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu3List() this.getBu3List()
this.showSuccess() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu3() { deleteBu3() {
this.bu3Service.delete(this.bu3).subscribe((response:any) => { this.bu3Service.delete(this.bu3).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu3List() this.getBu3List()
this.showSuccessDelete() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
...@@ -115,31 +188,19 @@ export class SectionRegistrationComponent implements OnInit { ...@@ -115,31 +188,19 @@ export class SectionRegistrationComponent implements OnInit {
this.selectBu2(bu2 || new MyBu2Model({ bu2id: this.bu2.bu2id })) this.selectBu2(bu2 || new MyBu2Model({ bu2id: this.bu2.bu2id }))
} }
filterBu2Modal() { filterBu2Modal() {
return this.bu2List.filter(x => x.bu2id.includes(this.bu2Modal.search) || return this.bu2List.filter(x => x.bu2id.toLowerCase().includes(this.bu2Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu2Modal.search) || x.tdesc.toLowerCase().includes(this.bu2Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu2Modal.search)) x.edesc.toLowerCase().includes(this.bu2Modal.search.toLowerCase()))
} }
selectBu2(bu2?: Bu2Model) { selectBu2(bu2?: Bu2Model) {
this.bu2 = new MyBu2Model(bu2 || {}) this.bu2 = new MyBu2Model(bu2 || {})
} }
showSuccess() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showSuccessEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
} }
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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-department-four-upload-modal">
<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>
...@@ -64,14 +65,24 @@ ...@@ -64,14 +65,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu7Table().length"> <tbody *ngIf="bu7ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu7ListLoading&&!filterBu7Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu7Table().length"> <tbody *ngIf="!bu7ListLoading&&filterBu7Table().length">
<tr <tr
*ngFor="let item of filterBu7Table() | slice:((bu7Table.currentPage-1) * 10) : (((bu7Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu7Table() | slice:((bu7Table.currentPage-1) * 10) : (((bu7Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -660,3 +671,33 @@ ...@@ -660,3 +671,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="sub-department-four-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนส่วน 4
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu6Model, MyBu6Model } from 'src/app/shared/model/bu6.model'; ...@@ -4,6 +4,7 @@ import { Bu6Model, MyBu6Model } from 'src/app/shared/model/bu6.model';
import { Bu7Model, MyBu7Model } from 'src/app/shared/model/bu7.model'; import { Bu7Model, MyBu7Model } from 'src/app/shared/model/bu7.model';
import { Bu6Service } from 'src/app/shared/services/bu6.service'; import { Bu6Service } from 'src/app/shared/services/bu6.service';
import { Bu7Service } from 'src/app/shared/services/bu7.service'; import { Bu7Service } from 'src/app/shared/services/bu7.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
...@@ -17,12 +18,17 @@ interface table { ...@@ -17,12 +18,17 @@ interface table {
}) })
export class SubDepartmentFourComponent implements OnInit { export class SubDepartmentFourComponent implements OnInit {
bu7List: Bu7Model[] = [] bu7List: Bu7Model[] = []
bu7ListLoading = false
bu7: Bu7Model = new MyBu7Model({}) bu7: Bu7Model = new MyBu7Model({})
bu7Table: table = { bu7Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu7Modal: table = { bu7Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -39,17 +45,71 @@ export class SubDepartmentFourComponent implements OnInit { ...@@ -39,17 +45,71 @@ export class SubDepartmentFourComponent implements OnInit {
constructor(private bu7Service: Bu7Service, constructor(private bu7Service: Bu7Service,
private bu6Service: Bu6Service, private bu6Service: Bu6Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu7List() this.getBu7List()
this.getBu6List() this.getBu6List()
} }
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.fileService.upload(formData, 'mbu7').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu7List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu7List() { getBu7List() {
this.bu7Service.getList().subscribe(response => { this.bu7ListLoading = true
this.bu7Service.getList().subscribe({
next: response => {
this.bu7List = response this.bu7List = response
this.bu7ListLoading = false
this.onBu7TableSearchChange() this.onBu7TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu7ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu7TableSearchChange() { onBu7TableSearchChange() {
...@@ -57,9 +117,9 @@ export class SubDepartmentFourComponent implements OnInit { ...@@ -57,9 +117,9 @@ export class SubDepartmentFourComponent implements OnInit {
this.bu7Table.page = Array.from({ length: Math.ceil(this.filterBu7Table().length / 10) }, (_, i) => i + 1); this.bu7Table.page = Array.from({ length: Math.ceil(this.filterBu7Table().length / 10) }, (_, i) => i + 1);
} }
filterBu7Table() { filterBu7Table() {
return this.bu7List.filter(x => x.bu7id.includes(this.bu7Table.search) || return this.bu7List.filter(x => x.bu7id.toLowerCase().includes(this.bu7Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu7Table.search) || x.tdesc.toLowerCase().includes(this.bu7Table.search.toLowerCase()) ||
x.edesc.includes(this.bu7Table.search)) x.edesc.toLowerCase().includes(this.bu7Table.search.toLowerCase()))
} }
selectBu7(bu7?: Bu7Model) { selectBu7(bu7?: Bu7Model) {
this.bu7 = new MyBu7Model(bu7 || {}) this.bu7 = new MyBu7Model(bu7 || {})
...@@ -80,23 +140,35 @@ export class SubDepartmentFourComponent implements OnInit { ...@@ -80,23 +140,35 @@ export class SubDepartmentFourComponent implements OnInit {
this.bu7Modal.page = Array.from({ length: Math.ceil(this.filterBu7Modal().length / 10) }, (_, i) => i + 1); this.bu7Modal.page = Array.from({ length: Math.ceil(this.filterBu7Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu7Modal() { filterBu7Modal() {
return this.bu7List.filter(x => x.bu7id.includes(this.bu7Modal.search) || return this.bu7List.filter(x => x.bu7id.toLowerCase().includes(this.bu7Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu7Modal.search) || x.tdesc.toLowerCase().includes(this.bu7Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu7Modal.search)) x.edesc.toLowerCase().includes(this.bu7Modal.search.toLowerCase()))
} }
addBu7() { addBu7() {
this.bu7Service.post({ ...this.bu7, parent: this.bu6.bu6id }).subscribe((response: any) => { this.bu7Service.post({ ...this.bu7, parent: this.bu6.bu6id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu7List() this.getBu7List()
this.showSuccessAdd() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu7() { deleteBu7() {
this.bu7Service.delete(this.bu7).subscribe((response: any) => { this.bu7Service.delete(this.bu7).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu7List() this.getBu7List()
this.showSuccessDelete() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
...@@ -116,31 +188,19 @@ export class SubDepartmentFourComponent implements OnInit { ...@@ -116,31 +188,19 @@ export class SubDepartmentFourComponent implements OnInit {
this.selectBu6(bu6 || new MyBu6Model({ bu6id: this.bu6.bu6id })) this.selectBu6(bu6 || new MyBu6Model({ bu6id: this.bu6.bu6id }))
} }
filterBu6Modal() { filterBu6Modal() {
return this.bu6List.filter(x => x.bu6id.includes(this.bu6Modal.search) || return this.bu6List.filter(x => x.bu6id.toLowerCase().includes(this.bu6Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu6Modal.search) || x.tdesc.toLowerCase().includes(this.bu6Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu6Modal.search)) x.edesc.toLowerCase().includes(this.bu6Modal.search.toLowerCase()))
} }
selectBu6(bu6?: Bu6Model) { selectBu6(bu6?: Bu6Model) {
this.bu6 = new MyBu6Model(bu6 || {}) this.bu6 = new MyBu6Model(bu6 || {})
} }
showSuccessAdd() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'แจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showSuccessEdit() {
this.toastr.success('แก้ไขข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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-department-one-upload-modal">
<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>
...@@ -65,14 +66,24 @@ ...@@ -65,14 +66,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu4Table().length"> <tbody *ngIf="bu4ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu4ListLoading&&!filterBu4Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu4Table().length"> <tbody *ngIf="!bu4ListLoading&&filterBu4Table().length">
<tr <tr
*ngFor="let item of filterBu4Table() | slice:((bu4Table.currentPage-1) * 10) : (((bu4Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu4Table() | slice:((bu4Table.currentPage-1) * 10) : (((bu4Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -680,3 +691,33 @@ ...@@ -680,3 +691,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="sub-department-one-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนส่วน 1
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu3Model, MyBu3Model } from 'src/app/shared/model/bu3.model'; ...@@ -4,6 +4,7 @@ import { Bu3Model, MyBu3Model } from 'src/app/shared/model/bu3.model';
import { Bu4Model, MyBu4Model } from 'src/app/shared/model/bu4.model'; import { Bu4Model, MyBu4Model } from 'src/app/shared/model/bu4.model';
import { Bu3Service } from 'src/app/shared/services/bu3.service'; import { Bu3Service } from 'src/app/shared/services/bu3.service';
import { Bu4Service } from 'src/app/shared/services/bu4.service'; import { Bu4Service } from 'src/app/shared/services/bu4.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
page: number[], page: number[],
...@@ -16,12 +17,17 @@ interface table { ...@@ -16,12 +17,17 @@ interface table {
}) })
export class SubDepartmentOneComponent implements OnInit { export class SubDepartmentOneComponent implements OnInit {
bu4List: Bu4Model[] = [] bu4List: Bu4Model[] = []
bu4ListLoading = false
bu4: Bu4Model = new MyBu4Model({}) bu4: Bu4Model = new MyBu4Model({})
bu4Table: table = { bu4Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu4Modal: table = { bu4Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -38,17 +44,71 @@ export class SubDepartmentOneComponent implements OnInit { ...@@ -38,17 +44,71 @@ export class SubDepartmentOneComponent implements OnInit {
constructor(private bu4Service: Bu4Service, constructor(private bu4Service: Bu4Service,
private bu3Service: Bu3Service, private bu3Service: Bu3Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu4List() this.getBu4List()
this.getBu3List() this.getBu3List()
} }
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.fileService.upload(formData, 'mbu4').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu4List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu4List() { getBu4List() {
this.bu4Service.getList().subscribe(response => { this.bu4ListLoading = true
this.bu4Service.getList().subscribe({
next: response => {
this.bu4List = response this.bu4List = response
this.bu4ListLoading = false
this.onBu4TableSearchChange() this.onBu4TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu4ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu4TableSearchChange() { onBu4TableSearchChange() {
...@@ -56,9 +116,9 @@ export class SubDepartmentOneComponent implements OnInit { ...@@ -56,9 +116,9 @@ export class SubDepartmentOneComponent implements OnInit {
this.bu4Table.page = Array.from({ length: Math.ceil(this.filterBu4Table().length / 10) }, (_, i) => i + 1); this.bu4Table.page = Array.from({ length: Math.ceil(this.filterBu4Table().length / 10) }, (_, i) => i + 1);
} }
filterBu4Table() { filterBu4Table() {
return this.bu4List.filter(x => x.bu4id.includes(this.bu4Table.search) || return this.bu4List.filter(x => x.bu4id.toLowerCase().includes(this.bu4Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu4Table.search) || x.tdesc.toLowerCase().includes(this.bu4Table.search.toLowerCase()) ||
x.edesc.includes(this.bu4Table.search)) x.edesc.toLowerCase().includes(this.bu4Table.search.toLowerCase()))
} }
selectBu4(bu4?: Bu4Model) { selectBu4(bu4?: Bu4Model) {
this.bu4 = new MyBu4Model(bu4 || {}) this.bu4 = new MyBu4Model(bu4 || {})
...@@ -79,23 +139,35 @@ export class SubDepartmentOneComponent implements OnInit { ...@@ -79,23 +139,35 @@ export class SubDepartmentOneComponent implements OnInit {
this.bu4Modal.page = Array.from({ length: Math.ceil(this.filterBu4Modal().length / 10) }, (_, i) => i + 1); this.bu4Modal.page = Array.from({ length: Math.ceil(this.filterBu4Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu4Modal() { filterBu4Modal() {
return this.bu4List.filter(x => x.bu4id.includes(this.bu4Modal.search) || return this.bu4List.filter(x => x.bu4id.toLowerCase().includes(this.bu4Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu4Modal.search) || x.tdesc.toLowerCase().includes(this.bu4Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu4Modal.search)) x.edesc.toLowerCase().includes(this.bu4Modal.search.toLowerCase()))
} }
addBu4() { addBu4() {
this.bu4Service.post({ ...this.bu4, parent: this.bu3.bu3id }).subscribe((response: any) => { this.bu4Service.post({ ...this.bu4, parent: this.bu3.bu3id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu4List() this.getBu4List()
this.showSuccess() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu4() { deleteBu4() {
this.bu4Service.delete(this.bu4).subscribe((response: any) => { this.bu4Service.delete(this.bu4).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu4List() this.getBu4List()
this.showSuccessDelete() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
...@@ -115,31 +187,19 @@ export class SubDepartmentOneComponent implements OnInit { ...@@ -115,31 +187,19 @@ export class SubDepartmentOneComponent implements OnInit {
this.selectBu3(bu3 || new MyBu3Model({ bu3id: this.bu3.bu3id })) this.selectBu3(bu3 || new MyBu3Model({ bu3id: this.bu3.bu3id }))
} }
filterBu3Modal() { filterBu3Modal() {
return this.bu3List.filter(x => x.bu3id.includes(this.bu3Modal.search) || return this.bu3List.filter(x => x.bu3id.toLowerCase().includes(this.bu3Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu3Modal.search) || x.tdesc.toLowerCase().includes(this.bu3Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu3Modal.search)) x.edesc.toLowerCase().includes(this.bu3Modal.search.toLowerCase()))
} }
selectBu3(bu3?: Bu3Model) { selectBu3(bu3?: Bu3Model) {
this.bu3 = new MyBu3Model(bu3 || {}) this.bu3 = new MyBu3Model(bu3 || {})
} }
showSuccess() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showSuccessEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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-department-three-upload-modal">
<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>
...@@ -64,14 +65,24 @@ ...@@ -64,14 +65,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu6Table().length"> <tbody *ngIf="bu6ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu6ListLoading&&!filterBu6Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu6Table().length"> <tbody *ngIf="!bu6ListLoading&&filterBu6Table().length">
<tr <tr
*ngFor="let item of filterBu6Table() | slice:((bu6Table.currentPage-1) * 10) : (((bu6Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu6Table() | slice:((bu6Table.currentPage-1) * 10) : (((bu6Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -660,3 +671,33 @@ ...@@ -660,3 +671,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="sub-department-three-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนส่วน 3
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu5Model, MyBu5Model } from 'src/app/shared/model/bu5.model'; ...@@ -4,6 +4,7 @@ import { Bu5Model, MyBu5Model } from 'src/app/shared/model/bu5.model';
import { Bu6Model, MyBu6Model } from 'src/app/shared/model/bu6.model'; import { Bu6Model, MyBu6Model } from 'src/app/shared/model/bu6.model';
import { Bu5Service } from 'src/app/shared/services/bu5.service'; import { Bu5Service } from 'src/app/shared/services/bu5.service';
import { Bu6Service } from 'src/app/shared/services/bu6.service'; import { Bu6Service } from 'src/app/shared/services/bu6.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
...@@ -17,12 +18,17 @@ interface table { ...@@ -17,12 +18,17 @@ interface table {
}) })
export class SubDepartmentThreeComponent implements OnInit { export class SubDepartmentThreeComponent implements OnInit {
bu6List: Bu6Model[] = [] bu6List: Bu6Model[] = []
bu6ListLoading = false
bu6: Bu6Model = new MyBu6Model({}) bu6: Bu6Model = new MyBu6Model({})
bu6Table: table = { bu6Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu6Modal: table = { bu6Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -39,17 +45,71 @@ export class SubDepartmentThreeComponent implements OnInit { ...@@ -39,17 +45,71 @@ export class SubDepartmentThreeComponent implements OnInit {
constructor(private bu6Service: Bu6Service, constructor(private bu6Service: Bu6Service,
private bu5Service: Bu5Service, private bu5Service: Bu5Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu6List() this.getBu6List()
this.getBu5List() this.getBu5List()
} }
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.fileService.upload(formData, 'mbu6').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu6List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu6List() { getBu6List() {
this.bu6Service.getList().subscribe(response => { this.bu6ListLoading = true
this.bu6Service.getList().subscribe({
next: response => {
this.bu6List = response this.bu6List = response
this.bu6ListLoading = false
this.onBu6TableSearchChange() this.onBu6TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu6ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu6TableSearchChange() { onBu6TableSearchChange() {
...@@ -57,9 +117,9 @@ export class SubDepartmentThreeComponent implements OnInit { ...@@ -57,9 +117,9 @@ export class SubDepartmentThreeComponent implements OnInit {
this.bu6Table.page = Array.from({ length: Math.ceil(this.filterBu6Table().length / 10) }, (_, i) => i + 1); this.bu6Table.page = Array.from({ length: Math.ceil(this.filterBu6Table().length / 10) }, (_, i) => i + 1);
} }
filterBu6Table() { filterBu6Table() {
return this.bu6List.filter(x => x.bu6id.includes(this.bu6Table.search) || return this.bu6List.filter(x => x.bu6id.toLowerCase().includes(this.bu6Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu6Table.search) || x.tdesc.toLowerCase().includes(this.bu6Table.search.toLowerCase()) ||
x.edesc.includes(this.bu6Table.search)) x.edesc.toLowerCase().includes(this.bu6Table.search.toLowerCase()))
} }
selectBu6(bu6?: Bu6Model) { selectBu6(bu6?: Bu6Model) {
this.bu6 = new MyBu6Model(bu6 || {}) this.bu6 = new MyBu6Model(bu6 || {})
...@@ -80,23 +140,35 @@ export class SubDepartmentThreeComponent implements OnInit { ...@@ -80,23 +140,35 @@ export class SubDepartmentThreeComponent implements OnInit {
this.bu6Modal.page = Array.from({ length: Math.ceil(this.filterBu6Modal().length / 10) }, (_, i) => i + 1); this.bu6Modal.page = Array.from({ length: Math.ceil(this.filterBu6Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu6Modal() { filterBu6Modal() {
return this.bu6List.filter(x => x.bu6id.includes(this.bu6Modal.search) || return this.bu6List.filter(x => x.bu6id.toLowerCase().includes(this.bu6Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu6Modal.search) || x.tdesc.toLowerCase().includes(this.bu6Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu6Modal.search)) x.edesc.toLowerCase().includes(this.bu6Modal.search.toLowerCase()))
} }
addBu6() { addBu6() {
this.bu6Service.post({ ...this.bu6, parent: this.bu5.bu5id }).subscribe((response: any) => { this.bu6Service.post({ ...this.bu6, parent: this.bu5.bu5id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu6List() this.getBu6List()
this.showSuccessAdd() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu6() { deleteBu6() {
this.bu6Service.delete(this.bu6).subscribe((response: any) => { this.bu6Service.delete(this.bu6).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu6List() this.getBu6List()
this.showSuccessDelete() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
...@@ -116,31 +188,19 @@ export class SubDepartmentThreeComponent implements OnInit { ...@@ -116,31 +188,19 @@ export class SubDepartmentThreeComponent implements OnInit {
this.selectBu5(bu5 || new MyBu5Model({ bu5id: this.bu5.bu5id })) this.selectBu5(bu5 || new MyBu5Model({ bu5id: this.bu5.bu5id }))
} }
filterBu5Modal() { filterBu5Modal() {
return this.bu5List.filter(x => x.bu5id.includes(this.bu5Modal.search) || return this.bu5List.filter(x => x.bu5id.toLowerCase().includes(this.bu5Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu5Modal.search) || x.tdesc.toLowerCase().includes(this.bu5Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu5Modal.search)) x.edesc.toLowerCase().includes(this.bu5Modal.search.toLowerCase()))
} }
selectBu5(bu5?: Bu5Model) { selectBu5(bu5?: Bu5Model) {
this.bu5 = new MyBu5Model(bu5 || {}) this.bu5 = new MyBu5Model(bu5 || {})
} }
showSuccessAdd() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'แจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showSuccessEdit() {
this.toastr.success('แก้ไขข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
} }
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
<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-department-two-upload-modal">
<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>
...@@ -64,14 +65,24 @@ ...@@ -64,14 +65,24 @@
</ng-container> </ng-container>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="!filterBu5Table().length"> <tbody *ngIf="bu5ListLoading">
<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>
</td>
</tr>
</tbody>
<tbody *ngIf="!bu5ListLoading&&!filterBu5Table().length">
<tr> <tr>
<td class="text-center" colspan="100%"> <td class="text-center" colspan="100%">
ไม่พบข้อมูล ไม่พบข้อมูล
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody *ngIf="filterBu5Table().length"> <tbody *ngIf="!bu5ListLoading&&filterBu5Table().length">
<tr <tr
*ngFor="let item of filterBu5Table() | slice:((bu5Table.currentPage-1) * 10) : (((bu5Table.currentPage-1) * 10) + 10);let i = index"> *ngFor="let item of filterBu5Table() | slice:((bu5Table.currentPage-1) * 10) : (((bu5Table.currentPage-1) * 10) + 10);let i = index">
<td class="text-center"> <td class="text-center">
...@@ -586,7 +597,7 @@ ...@@ -586,7 +597,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="#sub-department-two-alert-add-modal" (click)="addBu5(); showSuccessAdd()"> data-hs-overlay="#sub-department-two-alert-add-modal" (click)="addBu5()">
บันทึกข้อมูล บันทึกข้อมูล
</a> </a>
</div> </div>
...@@ -671,3 +682,33 @@ ...@@ -671,3 +682,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="sub-department-two-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าทะเบียนส่วน 2
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { Bu4Model, MyBu4Model } from 'src/app/shared/model/bu4.model'; ...@@ -4,6 +4,7 @@ import { Bu4Model, MyBu4Model } from 'src/app/shared/model/bu4.model';
import { Bu5Model, MyBu5Model } from 'src/app/shared/model/bu5.model'; import { Bu5Model, MyBu5Model } from 'src/app/shared/model/bu5.model';
import { Bu4Service } from 'src/app/shared/services/bu4.service'; import { Bu4Service } from 'src/app/shared/services/bu4.service';
import { Bu5Service } from 'src/app/shared/services/bu5.service'; import { Bu5Service } from 'src/app/shared/services/bu5.service';
import { FileService } from 'src/app/shared/services/file.service';
interface table { interface table {
currentPage: number, currentPage: number,
page: number[], page: number[],
...@@ -16,12 +17,17 @@ interface table { ...@@ -16,12 +17,17 @@ interface table {
}) })
export class SubDepartmentTwoComponent implements OnInit { export class SubDepartmentTwoComponent implements OnInit {
bu5List: Bu5Model[] = [] bu5List: Bu5Model[] = []
bu5ListLoading = false
bu5: Bu5Model = new MyBu5Model({}) bu5: Bu5Model = new MyBu5Model({})
bu5Table: table = { bu5Table: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
search: "" search: ""
} }
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
bu5Modal: table = { bu5Modal: table = {
currentPage: 1, currentPage: 1,
page: Array.from({ length: 1 }, (_, i) => i + 1), page: Array.from({ length: 1 }, (_, i) => i + 1),
...@@ -38,17 +44,71 @@ export class SubDepartmentTwoComponent implements OnInit { ...@@ -38,17 +44,71 @@ export class SubDepartmentTwoComponent implements OnInit {
constructor(private bu5Service: Bu5Service, constructor(private bu5Service: Bu5Service,
private bu4Service: Bu4Service, private bu4Service: Bu4Service,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getBu5List() this.getBu5List()
this.getBu4List() this.getBu4List()
} }
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.fileService.upload(formData, 'mbu5').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getBu5List()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_BU.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')
}
})
}
getBu5List() { getBu5List() {
this.bu5Service.getList().subscribe(response => { this.bu5ListLoading = true
this.bu5Service.getList().subscribe({
next: response => {
this.bu5List = response this.bu5List = response
this.bu5ListLoading = false
this.onBu5TableSearchChange() this.onBu5TableSearchChange()
this.cdr.detectChanges() this.cdr.detectChanges()
}, error: error => {
this.bu5ListLoading = false
this.cdr.detectChanges()
}
}) })
} }
onBu5TableSearchChange() { onBu5TableSearchChange() {
...@@ -56,9 +116,9 @@ export class SubDepartmentTwoComponent implements OnInit { ...@@ -56,9 +116,9 @@ export class SubDepartmentTwoComponent implements OnInit {
this.bu5Table.page = Array.from({ length: Math.ceil(this.filterBu5Table().length / 10) }, (_, i) => i + 1); this.bu5Table.page = Array.from({ length: Math.ceil(this.filterBu5Table().length / 10) }, (_, i) => i + 1);
} }
filterBu5Table() { filterBu5Table() {
return this.bu5List.filter(x => x.bu5id.includes(this.bu5Table.search) || return this.bu5List.filter(x => x.bu5id.toLowerCase().includes(this.bu5Table.search.toLowerCase()) ||
x.tdesc.includes(this.bu5Table.search) || x.tdesc.toLowerCase().includes(this.bu5Table.search.toLowerCase()) ||
x.edesc.includes(this.bu5Table.search)) x.edesc.toLowerCase().includes(this.bu5Table.search.toLowerCase()))
} }
selectBu5(bu5?: Bu5Model) { selectBu5(bu5?: Bu5Model) {
this.bu5 = new MyBu5Model(bu5 || {}) this.bu5 = new MyBu5Model(bu5 || {})
...@@ -79,23 +139,35 @@ export class SubDepartmentTwoComponent implements OnInit { ...@@ -79,23 +139,35 @@ export class SubDepartmentTwoComponent implements OnInit {
this.bu5Modal.page = Array.from({ length: Math.ceil(this.filterBu5Modal().length / 10) }, (_, i) => i + 1); this.bu5Modal.page = Array.from({ length: Math.ceil(this.filterBu5Modal().length / 10) }, (_, i) => i + 1);
} }
filterBu5Modal() { filterBu5Modal() {
return this.bu5List.filter(x => x.bu5id.includes(this.bu5Modal.search) || return this.bu5List.filter(x => x.bu5id.toLowerCase().includes(this.bu5Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu5Modal.search) || x.tdesc.toLowerCase().includes(this.bu5Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu5Modal.search)) x.edesc.toLowerCase().includes(this.bu5Modal.search.toLowerCase()))
} }
addBu5() { addBu5() {
this.bu5Service.post({ ...this.bu5, parent: this.bu4.bu4id }).subscribe((response: any) => { this.bu5Service.post({ ...this.bu5, parent: this.bu4.bu4id }).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu5List() this.getBu5List()
this.showSuccessAdd() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
deleteBu5() { deleteBu5() {
this.bu5Service.delete(this.bu5).subscribe((response: any) => { this.bu5Service.delete(this.bu5).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getBu5List() this.getBu5List()
this.showSuccessDelete() } else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
} }
}) })
} }
...@@ -115,31 +187,19 @@ export class SubDepartmentTwoComponent implements OnInit { ...@@ -115,31 +187,19 @@ export class SubDepartmentTwoComponent implements OnInit {
this.selectBu4(bu4 || new MyBu4Model({ bu4id: this.bu4.bu4id })) this.selectBu4(bu4 || new MyBu4Model({ bu4id: this.bu4.bu4id }))
} }
filterBu4Modal() { filterBu4Modal() {
return this.bu4List.filter(x => x.bu4id.includes(this.bu4Modal.search) || return this.bu4List.filter(x => x.bu4id.toLowerCase().includes(this.bu4Modal.search.toLowerCase()) ||
x.tdesc.includes(this.bu4Modal.search) || x.tdesc.toLowerCase().includes(this.bu4Modal.search.toLowerCase()) ||
x.edesc.includes(this.bu4Modal.search)) x.edesc.toLowerCase().includes(this.bu4Modal.search.toLowerCase()))
} }
selectBu4(bu4?: Bu4Model) { selectBu4(bu4?: Bu4Model) {
this.bu4 = new MyBu4Model(bu4 || {}) this.bu4 = new MyBu4Model(bu4 || {})
} }
showSuccessAdd() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'แจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showSuccessEdit() {
this.toastr.success('แก้ไขข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
} }
/* สไตล์ของแถบเมนู */
.nav-tabs {
display: flex;
border-bottom: 2px solid #ccc; /* เส้นใต้ */
border-top: 2px solid #ccc;
width: 100%;
cursor: pointer;
border-top: 2px solid #ccc;
}
.nav-item {
list-style: none;
margin-right: 40px; /* ช่องว่างระหว่างเมนู */
}
.nav-link {
text-decoration: none;
padding: 10px 20px;
display: inline-block;
font-size: medium;
text-align: left;
padding-left: 0px;
padding-right: 0px;
}
.nav-link:hover {
background-color: #f0f0f0; /* เปลี่ยนสีเมื่อ hover */
}
.nav-link.active {
color: #569bf5; /* สีตัวอักษรในสถานะ active */
font-size: medium;
border-bottom: 3.5px solid #569bf5; /* เส้นใต้ */
}
.tab-content {
margin-top: 20px;
}
.tab-pane.active {
display: block;
}
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
<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="#employee-categories-page-upload-modal"> data-hs-overlay="#employee-categories-upload-modal">
<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>
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
<div class="flex justify-end"> <div class="flex justify-end">
<ng-container *ngIf="modalStatus=='add'||modalStatus=='edit'"> <ng-container *ngIf="modalStatus=='add'||modalStatus=='edit'">
<button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger" <button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger"
data-hs-overlay="#employee-categories-page-modal"> data-hs-overlay="#employee-categories-page-alert-modal">
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<i class="ti ti-circle-x fs-xxl"></i> <i class="ti ti-circle-x fs-xxl"></i>
</button> </button>
...@@ -273,3 +273,33 @@ ...@@ -273,3 +273,33 @@
</div> </div>
</div> </div>
</div> </div>
<div id="employee-categories-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<h5 class="text-xxl font-bold text-white">
นำเข้าประเภทพนักงาน
</h5>
</div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 p-2">
<div class="flex rounded-md">
<input #fileInput type="file" (change)="onFileSelected($event)" hidden>
<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 cursor-pointer">
<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>
</button>
</div>
<div class="flex justify-center mt-2rem mb-1rem space-x-4">
<button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด
</button>
</div>
</div>
</div>
</div>
</div>
...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angu ...@@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angu
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { EmpTypeModel, MyEmpTypeModel } from 'src/app/shared/model/employee-type.model'; import { EmpTypeModel, MyEmpTypeModel } from 'src/app/shared/model/employee-type.model';
import { EmpTypeService } from 'src/app/shared/services/employee-type.service'; import { EmpTypeService } from 'src/app/shared/services/employee-type.service';
import { FileService } from 'src/app/shared/services/file.service';
export interface DataModel { export interface DataModel {
codeId: string codeId: string
tdesc: string tdesc: string
...@@ -35,23 +36,75 @@ export class EmployeeCategories { ...@@ -35,23 +36,75 @@ export class EmployeeCategories {
dataSelect: DataModel = { codeId: "", tdesc: "", edesc: "", companyId: "" } dataSelect: DataModel = { codeId: "", tdesc: "", edesc: "", companyId: "" }
itemToDelete: EmpTypeModel | null = null; itemToDelete: EmpTypeModel | null = null;
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
constructor(private empTypeService: EmpTypeService, constructor(private empTypeService: EmpTypeService,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getEmpTypeList() this.getEmpTypeList()
} }
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.fileService.upload(formData, 'employment_type').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getEmpTypeList()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_MEMPLOYMENTTYPE.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')
}
})
}
getEmpTypeList() { getEmpTypeList() {
this.dataLoading = true
this.empTypeService.getList().subscribe({ this.empTypeService.getList().subscribe({
next: response => { next: response => {
this.emp_typelist = response.map(x => ({ check: false, data: { codeId: x.codeId, tdesc: x.tdesc, edesc: x.edesc, companyId: x.companyId } })) this.emp_typelist = response.map(x => ({ check: false, data: { codeId: x.codeId, tdesc: x.tdesc, edesc: x.edesc, companyId: x.companyId } }))
this.dataLoading = false
this.searchChange(); this.searchChange();
this.cdr.detectChanges(); this.cdr.detectChanges();
}, }, error: error => {
error: err => { this.dataLoading = false
console.error('Error fetching employee types:', err); console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
} }
}); });
} }
...@@ -63,17 +116,14 @@ export class EmployeeCategories { ...@@ -63,17 +116,14 @@ export class EmployeeCategories {
emp_typeListFilter() { emp_typeListFilter() {
return this.emp_typelist.filter(x => { return this.emp_typelist.filter(x => {
const data = x.data const data = x.data
const match = data.codeId.includes(this.search) || data.tdesc.includes(this.search) || data.edesc.includes(this.search); const match = data.codeId.toLowerCase().includes(this.search) || data.tdesc.toLowerCase().includes(this.search) || data.edesc.toLowerCase().includes(this.search);
return match; return match;
}); });
} }
setData(data?: DataModel) { setData(data?: DataModel) {
this.dataSelect = JSON.parse(JSON.stringify(data || { code: "", tdesc: "", edesc: "", companyId: "" })); this.dataSelect = JSON.parse(JSON.stringify(data || { code: "", tdesc: "", edesc: "", companyId: "" }));
} }
// selectEmp_type(emp_type?: EmpTypeModel) {
// // this.showSuccess()
// this.emp_type = new MyEmpTypeModel(emp_type || {})
// }
addEmp_type() { addEmp_type() {
const body = new MyEmpTypeModel({ codeId: this.dataSelect.codeId, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, companyId: this.dataSelect.companyId }) const body = new MyEmpTypeModel({ codeId: this.dataSelect.codeId, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, companyId: this.dataSelect.companyId })
this.empTypeService.post(body).subscribe({ this.empTypeService.post(body).subscribe({
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
<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="#employee-level-modal-upload"> data-hs-overlay="#employee-level-upload-modal">
<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>
...@@ -210,28 +210,30 @@ ...@@ -210,28 +210,30 @@
</div> </div>
</div> </div>
<div id="employee-level-modal-upload" class="hs-overlay hidden ti-modal"> <div id="employee-level-upload-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)]"> <div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] rounded-md">
<div class="max-h-full overflow-hidden ti-modal-content h-96"> <div class="ti-modal-header bg-primary !rounded-none !rounded-t-sm">
<div class="ti-modal-header bg-primary">
<h5 class="text-xxl font-bold text-white"> <h5 class="text-xxl font-bold text-white">
นำเข้าข้อมูลบริษัท นำเข้าระดับพนักงาน (PL)
</h5> </h5>
</div> </div>
<div class="ti-modal-body max-h-full overflow-hidden ti-modal-content !rounded-t-none !rounded-b-sm">
<h1 class="mt-2" style="text-align: center;">ไฟล์</h1> <h1 class="mt-2" style="text-align: center;">ไฟล์</h1>
<div class="mt-2 px-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 type="file" (change)="onFileSelected($event)" hidden>
class="ti-form-input rounded-none ltr:rounded-l-md rtl:rounded-r-md focus:z-10"> <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-primary text-white hover:bg-primary focus:z-10 focus:outline-none focus:ring-0 focus:ring-primary 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-primary" href="javascript:void(0);"> <button type="submit" class="ti-btn ti-btn-secondary" (click)="uploadFile()"
[disabled]="!selectedFile">
อัปโหลด อัปโหลด
</a> </button>
</div> </div>
</div> </div>
</div> </div>
...@@ -248,7 +250,7 @@ ...@@ -248,7 +250,7 @@
<div class="flex justify-end"> <div class="flex justify-end">
<ng-container *ngIf="modalStatus=='add'||modalStatus=='edit'"> <ng-container *ngIf="modalStatus=='add'||modalStatus=='edit'">
<button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger" <button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger"
data-hs-overlay="#employee-level-page-modal"> data-hs-overlay="#employee-level-page-alert-modal">
<span class="sr-only">Close</span> <span class="sr-only">Close</span>
<i class="ti ti-circle-x fs-xxl"></i> <i class="ti ti-circle-x fs-xxl"></i>
</button> </button>
......
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { MyPLModel, PLModel } from 'src/app/shared/model/pl.model'; import { MyPLModel, PLModel } from 'src/app/shared/model/pl.model';
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';
export interface DataModel { export interface DataModel {
plId: string plId: string
...@@ -34,24 +35,76 @@ export class EmployeeLevel implements OnInit { ...@@ -34,24 +35,76 @@ export class EmployeeLevel implements OnInit {
dataSelect: DataModel = { plId: "", tdesc: "", edesc: "", companyId: "" } dataSelect: DataModel = { plId: "", tdesc: "", edesc: "", companyId: "" }
itemToDelete: PLModel | null = null; itemToDelete: PLModel | null = null;
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
constructor(private plService: PLService, constructor(private plService: PLService,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
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.fileService.upload(formData, 'pl').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getPLList()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
downloadFile() {
const fileName = 'IMPORT_PL.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.dataLoading = true
this.plService.getList().subscribe({ this.plService.getList().subscribe({
next: response => { next: response => {
this.plList = response.map(x => ({ check: false, data: { plId: x.plId, tdesc: x.tdesc, edesc: x.edesc, companyId: x.companyId } })) this.plList = response.map(x => ({ check: false, data: { plId: x.plId, tdesc: x.tdesc, edesc: x.edesc, companyId: x.companyId } }))
this.dataLoading = false
this.searchChange(); this.searchChange();
this.cdr.detectChanges(); this.cdr.detectChanges();
}, }, error: error => {
error: err => { this.dataLoading = false
console.error('Error fetching employee types:', err); console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
} }
}); });
} }
...@@ -64,7 +117,7 @@ export class EmployeeLevel implements OnInit { ...@@ -64,7 +117,7 @@ export class EmployeeLevel implements OnInit {
plListFilter() { plListFilter() {
return this.plList.filter(x => { return this.plList.filter(x => {
const data = x.data const data = x.data
const match = data.plId.includes(this.search) || data.tdesc.includes(this.search) || data.edesc.includes(this.search); const match = data.plId.toLowerCase().includes(this.search) || data.tdesc.toLowerCase().includes(this.search) || data.edesc.toLowerCase().includes(this.search);
return match; return match;
}); });
} }
......
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { MyPositionModel, PositionModel } from 'src/app/shared/model/position.model'; import { MyPositionModel, PositionModel } from 'src/app/shared/model/position.model';
import { FileService } from 'src/app/shared/services/file.service';
import { PositionService } from 'src/app/shared/services/position.service'; import { PositionService } from 'src/app/shared/services/position.service';
export interface DataModel {
positionId: string
tdesc: string
edesc: string
consolidate: string
shortName: string
companyId: string
}
@Component({ @Component({
selector: 'app-position-unit', selector: 'app-position-unit',
...@@ -20,22 +29,82 @@ export class PositionUnitComponent implements OnInit { ...@@ -20,22 +29,82 @@ export class PositionUnitComponent implements OnInit {
} }
currentPage = 1 currentPage = 1
selectedItems: string[] = []; selectedItems: string[] = [];
search = ""
selectedFile: File | null = null;
selectedFileName: string = 'กรุณาเลือกไฟล์';
modalStatus = 'add'
page = Array.from({ length: 1 }, (_, i) => i + 1); page = Array.from({ length: 1 }, (_, i) => i + 1);
positionList: PositionModel[] = [] positionList: { check: boolean, data: DataModel }[] = []
position: PositionModel = new MyPositionModel({}) position: PositionModel = new MyPositionModel({})
search = "" dataLoading = false
dataSelect: DataModel = { positionId: "", tdesc: "", edesc: "", consolidate: "", shortName: "", companyId: "" }
constructor(private positionService: PositionService, constructor(private positionService: PositionService,
private toastr: ToastrService, private toastr: ToastrService,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef,
private fileService: FileService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.getPositionList() this.getPositionList()
} }
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.fileService.upload(formData, 'mposition').subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getPositionList()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
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')
}
})
}
getPositionList() { getPositionList() {
this.positionService.getList().subscribe(response => { this.dataLoading = true
this.positionList = response.map(x => new MyPositionModel(x)) this.positionService.getList().subscribe({
next: response => {
this.positionList = response.map(x => ({ check: false, data: { positionId: x.positionId, tdesc: x.tdesc, edesc: x.edesc, consolidate: x.consolidate, shortName: x.shortName, companyId: x.companyId } }))
this.dataLoading = false
this.searchChange() this.searchChange()
this.cdr.detectChanges();
}, error: error => {
this.dataLoading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges() this.cdr.detectChanges()
}
}) })
} }
searchChange() { searchChange() {
...@@ -43,83 +112,63 @@ export class PositionUnitComponent implements OnInit { ...@@ -43,83 +112,63 @@ export class PositionUnitComponent implements OnInit {
this.page = Array.from({ length: Math.ceil(this.positionListFilter().length / 10) }, (_, i) => i + 1); this.page = Array.from({ length: Math.ceil(this.positionListFilter().length / 10) }, (_, i) => i + 1);
} }
positionListFilter() { positionListFilter() {
return this.positionList.filter(x => x.positionId.includes(this.search) || return this.positionList.filter(x => {
x.tdesc.includes(this.search) || const data = x.data;
x.edesc.includes(this.search)) const searchLower = this.search.toLowerCase();
}
selectPosition(position?: PositionModel) {
// this.showSuccess()
this.position = new MyPositionModel(position || {})
}
showSuccess() { return (
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { (data.positionId?.toLowerCase() || '').includes(searchLower) ||
timeOut: 3000, (data.tdesc?.toLowerCase() || '').includes(searchLower) ||
positionClass: 'toast-top-right', (data.edesc?.toLowerCase() || '').includes(searchLower) ||
(data.consolidate?.toLowerCase() || '').includes(searchLower) ||
(data.shortName?.toLowerCase() || '').includes(searchLower)
);
}); });
} }
showSuccesssEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', { setData(data?: DataModel) {
timeOut: 3000, this.dataSelect = JSON.parse(JSON.stringify(data || { positionId: "", tdesc: "", edesc: "", consolidate: "", shortName: "", companyId: "" }));
positionClass: 'toast-top-right',
});
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
addPosition() { addPosition() {
this.positionService.post(this.position).subscribe((response: any) => { const body = new MyPositionModel({ positionId: this.dataSelect.positionId, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, consolidate: this.dataSelect.consolidate, shortName: this.dataSelect.shortName, companyId: this.dataSelect.companyId })
this.positionService.post(body).subscribe({
next: response => {
if (response.success) { if (response.success) {
this.showAlert(response.message, 'success')
this.getPositionList() this.getPositionList()
this.showSuccess() } else {
} this.showAlert(response.message, 'error')
})
} }
deletePosition() { }, error: error => {
this.positionService.delete(this.position).subscribe((response: any) => { this.showAlert(error.message, 'error')
if (response.success) {
this.getPositionList()
this.showSuccessDelete()
} }
}) })
} }
toggleSelection(positionId: string, event: Event) { deletePosition() {
const checked = (event.target as HTMLInputElement).checked; let body: PositionModel | PositionModel[] = []
if (checked) { if (this.dataSelect.positionId) {
this.selectedItems.push(positionId); body = new MyPositionModel({ positionId: this.dataSelect.positionId, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, consolidate: this.dataSelect.consolidate, shortName: this.dataSelect.shortName, companyId: this.dataSelect.companyId })
} else { } else {
this.selectedItems = this.selectedItems.filter(id => id !== positionId); body = this.positionList.filter(x => x.check).map(x => new MyPositionModel({ positionId: x.data.positionId, tdesc: x.data.tdesc, edesc: x.data.edesc, consolidate: x.data.consolidate, shortName: x.data.shortName, companyId: x.data.companyId }))
} }
} this.positionService.delete(body).subscribe({
toggleSelectAll(event: Event) { next: response => {
const checked = (event.target as HTMLInputElement).checked; if (response.success) {
if (checked) { this.showAlert(response.message, 'success')
this.selectedItems = this.positionListFilter().map(item => item.positionId); this.getPositionList()
} else { } else {
this.selectedItems = []; this.showAlert(response.message, 'error')
} }
}, error: error => {
this.showAlert(error.message, 'error')
} }
deleteSelectedItems() { })
if (this.selectedItems.length === 0) {
alert("เลือกข้อมูลก่อนลบ");
return;
}
const selectedGroups = this.positionListFilter().filter(item => this.selectedItems.includes(item.positionId));
this.positionService.delete(selectedGroups).subscribe({
next: (response) => {
console.log("ลบสำเร็จ", response);
this.selectedItems = [];
this.getPositionList();
this.showSuccessDelete()
},
error: (error) => {
console.error("เกิดข้อผิดพลาดในการลบ", error);
} }
showAlert(text: string, type: 'success' | 'error') {
this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
}); });
} }
} }
......
import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
@Component({
selector: 'app-add-group-grade',
templateUrl: './add-group-grade.component.html',
styleUrls: ['./add-group-grade.component.scss']
})
export class AddGroupGradeComponent implements OnInit {
@Input() statusGroup = 'add' ;
@Output() sendEdit: EventEmitter<boolean> = new EventEmitter<boolean>();
activeTab: string = 'details-add';
isChecked: boolean = false;
// ข้อมูลที่จะใช้แสดงในตาราง
@Input() items: any[] = [
['1', '', 'CC'],
['2', '', 'MC'],
['3', '', 'PC']
];
// ฟังก์ชันในการเปลี่ยนแท็บ
changeTab(tab: { id: string, text: string }) {
this.activeTab = tab.id;
}
onEdit() {
this.sendEdit.emit(false);
}
// ฟังก์ชันในการบันทึกข้อมูลที่แก้ไข
saveData(event: any, id: any): void {
const updatedText = event.target.innerText; // ข้อความที่พิมพ์เข้าไป
// เก็บข้อมูลใน localStorage
localStorage.setItem(`item-${id}`, updatedText);
// ฟังก์ชันอัปเดตข้อมูล (หากต้องการส่งไปยัง API)
this.updateItem(id, updatedText);
}
// ฟังก์ชันในการอัพเดตข้อมูล
updateItem(id: any, updatedText: string): void {
// ส่งข้อมูลไปยัง API เพื่อบันทึกข้อมูลในฐานข้อมูล
// ตัวอย่างเช่น:
// this.myService.updateItem(id, updatedText).subscribe(response => {
// this.showSuccessEdit(); // เรียกฟังก์ชันแจ้งเตือน
// });
}
// เมื่อหน้าเว็บโหลดใหม่ดึงข้อมูลจาก localStorage
ngOnInit(): void {
this.items.forEach(item => {
const savedText = localStorage.getItem(`item-${item[0]}`);
if (savedText) {
item[1] = savedText; // ใช้ข้อมูลที่เก็บไว้
}
});
}
modalOptions: {
[nameModal: string]: {
isModalOpen: boolean;
modalSize: string;
backdropClose: boolean;
};
} = {
"add": { isModalOpen: false, modalSize: 'm', backdropClose: true },
"edit": { isModalOpen: false, modalSize: 'm', backdropClose: true }
};
openModal(name: string, size: string, closeOnBackdrop?: boolean) {
this.modalOptions[name].modalSize = size;
this.modalOptions[name].backdropClose = closeOnBackdrop || false;
this.modalOptions[name].isModalOpen = true;
this.currentModal = name;
document.body.style.overflow = 'hidden';
}
closeModal(name: string) {
this.modalOptions[name].isModalOpen = false;
if (!this.isAnyModalOpen()) {
document.body.style.overflow = '';
}
}
isAnyModalOpen(): boolean {
return Object.values(this.modalOptions).some(modal => modal.isModalOpen);
}
// ฟังก์ชันสำหรับการเพิ่ม ลบ หรือแก้ไข ข้อมูล
addUser() {
}
currentModal = "";
constructor(private toastr: ToastrService) { }
// แสดงข้อความแจ้งเตือนเมื่อการบันทึกสำเร็จ
showSuccessAdd() {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
showSuccessEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
}
<div class="flex justify-between">
<div class="flex">
<!-- Content ของ div แรก -->
<div class="flex">
<button type="button"
class="ti-btn text-primary hover:bg-blue-100 focus:ring-blue-500 dark:focus:ring-offset-white/10 h-10 m-0 shadow-md"
(click)="onEdit()">
<i class="ti ti-chevron-left"></i>
ย้อนกลับ
</button>
<div class="text-2xl font-bold py-2 text-primary px-2">
แก้ไขกลุ่มเกรด
</div>
</div>
</div>
<div class="flex justify-end">
<div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-success h-10 m-0 shadow-md"
data-hs-overlay="#edit-group-grade-alert-add-modal">
<i class="ri-save-3-line"></i>
Save
</button>
</div>
<div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-indigo h-10 m-0 shadow-md">
<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"
transform="rotate(45)matrix(-1, 0, 0, 1, 0, 0)">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path d="M15 49A24 24 0 0 1 32 8"></path>
<path d="M49 15a24 24 0 0 1-17 41"></path>
<polyline points="15.03 40 15.03 48.97 8 48.97"></polyline>
<polyline points="48.97 24 48.97 15.03 56 15.03"></polyline>
</g>
</svg>
Clear
</button>
</div>
<div class="px-1">
<button href="javascript:void(0);" class="ti-btn ti-btn-soft-warning h-10 m-0 shadow-md">
<i class="ti ti-book fs-l"></i>
Help
</button>
</div>
</div>
</div>
<div class="body-content">
<div class="page">
<div class="border-b border-gray-200 dark:border-white/10 px-8">
<nav class="flex rtl:space-x-reverse space-x-5" style="padding-top: 20px;">
<a class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900 active"
href="javascript:void(0);" id="underline-item-1" data-hs-tab="#underline-1"
aria-controls="underline-1" (click)="activeTab = 'details-edit'">
รายละเอียด
</a>
<a class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900"
href="javascript:void(0);" id="underline-item-2" data-hs-tab="#underline-2"
aria-controls="underline-2" (click)="activeTab = 'grade-register'">
ทะเบียนเกรด
</a>
</nav>
</div>
<div class="mt-3 px-3rem">
<div *ngIf="activeTab === 'details-edit'" id="underline-1" role="tabpanel"
aria-labelledby="underline-item-1">
<div class="page px-rem">
<label for="input-label" class="ti-form-label">กำหนดรหัสกลุ่มเกรด</label>
<input type="text" id="input-label" class="ti-form-input w-1/4 bg-input-readonly" readonly [ngModel]="dataSelect.code">
<label for="detail_th" class="ti-form-label mt-2rem">รายละเอียด (ไทย)*</label>
<input type="text" id="detail_th" class="ti-form-input w-1/2" [ngModel]="dataSelect.tdesc">
<label for="detail_eng" class="ti-form-label mt-2rem">รายละเอียด (อังกฤษ)</label>
<input type="text" id="detail_eng" class="ti-form-input w-1/2" placeholder="">
</div>
</div>
<div *ngIf="activeTab === 'grade-register'" id="details-tab" id="underline-2" role="tabpanel"
aria-labelledby="underline-item-2">
<app-sub-grade-registration></app-sub-grade-registration>
</div>
</div>
</div>
</div>
<div id="edit-group-grade-alert-add-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] flex items-center">
<div class="max-h-full overflow-hidden ti-modal-content-alert w-full">
<div class="ti-modal-header">
<h3 class="text-xxl font-bold text-primary">
แจ้งเตือน
</h3>
<div class="flex justify-end">
<button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger"
data-hs-overlay="#edit-group-grade-alert-add-modal">
<span class="sr-only">Close</span>
<i class="ti ti-circle-x fs-xxl"></i>
</button>
</div>
</div>
<div class="ti-modal-body ">
<p class="mt-1 text-gray-800 dark:text-white/70">
ยืนยันการเพิ่มข้อมูลหรือไม่!
</p>
<div class="flex justify-end mt-2rem mb-1rem">
<button type="button"
class="hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10"
data-hs-overlay="#edit-group-grade-alert-add-modal">
ย้อนกลับ
</button>
<a class="ti-btn ti-btn-success" href="javascript:void(0);"
data-hs-overlay="#edit-group-grade-alert-add-modal" (click)="addUser();showSuccessAdd()">
เพิ่มข้อมูล
</a>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
.button-clear {
position: absolute;
top: 96px;
z-index: 1;
right: 41vw;
}
.button-help {
position: absolute;
top: 0px;
z-index: 1;
right: 0vw;
margin: 4.2rem;
margin-right: 10px; /* เพิ่มใหม่ 12/16*/
}
.htable{
height: 400px;
}
table.ti-custom-table thead {
height: 60px;
}
table.ti-custom-table thead th span {
font-size: 12px;
font-weight: bold;
}
.ti-custom-table td{
padding-left: 0.9rem;
padding-right: 1rem;
}
.ti-custom-table thead th:first-child {
width: 120px; /* ปรับความกว้างตามที่ต้องการ */
text-align: left; /* จัดตำแหน่งข้อความถ้าต้องการ */
padding-left: 2px;
padding-right: 2px;
}
.ti-custom-table thead th:last-child {
width: 400px; /* ปรับความกว้างตามที่ต้องการ */
}
a.custom-link {
padding: 10px 40px; /* ปรับ padding ให้เพิ่มขนาด */
}
/* สไตล์ของแถบเมนู */
.nav-tabs {
display: flex;
width: 100%;
cursor: pointer;
margin-bottom: 10px;
height: 20%;
}
.nav-item {
list-style: none;
margin-right: 10px; /* ช่องว่างระหว่างเมนู */
}
.nav-link {
text-decoration: none;
padding: 10px 20px;
display: inline-block;
font-size: large;
border-width: 2px 2px 0px 2px;
border-style: solid;
border-color: #ccc;
border-radius: 5px 5px 0px 0px;
}
.nav-link:hover {
background-color: #f0f0f0; /* เปลี่ยนสีเมื่อ hover */
}
.nav-link.active {
color: #ffffff; /* สีตัวอักษรในสถานะ active */
font-size: large;
border-bottom: 3.5px solid rgb(var(--color-primary)); /* เส้นใต้ */
background-color: rgb(var(--color-primary));
border-width: 2px 2px 0px 2px;
border-style: solid;
border-color: rgb(var(--color-primary));
border-radius: 5px 5px 0px 0px;
}
.tab-content {
margin-top: 20px;
}
.tab-pane.active {
display: block;
}
.nav-item-text {
list-style: none;
margin-right: 10px; /* ช่องว่างระหว่างเมนู */
}
.nav-link-text {
text-decoration: none;
display: inline-block;
font-size: large;
color: #569bf5;
border-bottom: 2px solid #569bf5;
line-height: 0.8;
}
.ti-pagination .page-link.active {
background-color: #569bf5;
color: white;
border-radius: 50%;
padding: 8px 12px;
}
.box-body{
padding: 0rem;
}
.page{
min-height: 0vh;
}
.ti-modal-content {
padding: 1rem;
height: 650px;
overflow-y: auto;
}
.ti-modal-content-alert{
width: 35%; /* ความกว้างที่คุณต้องการ */
position: absolute; /* ทำให้สามารถจัดตำแหน่งได้ */
top: 50%; /* ให้อยู่กลางในแนวตั้ง */
left: 50%; /* ให้อยู่กลางในแนวนอน */
transform: translate(-50%, -50%); /* เคลื่อนที่ modal กลับมาให้ตรงกลาง */
background-color: #ffffff;
}
.header-title-type {
width: 100%;
min-height: 50px; /* ใช้ min-height เพื่อให้มีความยืดหยุ่น */
justify-content: space-between; /* จัดเรียงองค์ประกอบภายใน */
align-items: center; /* จัดกลางแนวตั้ง */
padding-top: 50px;
padding-bottom: 1rem;
}
.body-content{
margin-bottom: 30px;
overflow-y: auto;
}
.bg-input-readonly{
background-color: rgb(241 245 249);
}
.ciricon {
height: 12px; /* กำหนดความสูงของวงกลม */
width: 12px; /* กำหนดความกว้างของวงกลม */
background-color: #ffffff;
font-weight: bold;
display: flex; /* ใช้ Flexbox */
justify-content: center; /* จัดตำแหน่งแนวนอนให้กึ่งกลาง */
align-items: center; /* จัดตำแหน่งแนวตั้งให้กึ่งกลาง */
border-radius: 2px; /* ทำให้เป็นวงกลม */
}
.ri-close-line {
font-size: 15px; /* ขนาดไอคอน */
}
\ No newline at end of file
import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
export interface DataModel {
check: boolean;
code: string;
tdesc: string;
edesc: string;
}
@Component({
selector: 'app-edit-group-grade',
templateUrl: './edit-group-grade.component.html',
styleUrls: ['./edit-group-grade.component.scss']
})
export class EditGroupGradeComponent implements OnInit {
@Input() dataSelect = { check: false, code: '', tdesc: '', edesc: '' }
@Output() sendEdit: EventEmitter<boolean> = new EventEmitter<boolean>();
activeTab: string = 'details-edit';
isChecked: boolean = false;
// ข้อมูลที่จะใช้แสดงในตาราง
@Input() items: any[] = [
['1', '', 'CC'],
['2', '', 'MC'],
['3', '', 'PC']
];
// ฟังก์ชันในการเปลี่ยนแท็บ
changeTab(tab: { id: string, text: string }) {
this.activeTab = tab.id;
}
onEdit() {
this.sendEdit.emit(false);
}
// ฟังก์ชันในการบันทึกข้อมูลที่แก้ไข
saveData(event: any, id: any): void {
const updatedText = event.target.innerText; // ข้อความที่พิมพ์เข้าไป
// เก็บข้อมูลใน localStorage
localStorage.setItem(`item-${id}`, updatedText);
// ฟังก์ชันอัปเดตข้อมูล (หากต้องการส่งไปยัง API)
this.updateItem(id, updatedText);
}
// ฟังก์ชันในการอัพเดตข้อมูล
updateItem(id: any, updatedText: string): void {
// ส่งข้อมูลไปยัง API เพื่อบันทึกข้อมูลในฐานข้อมูล
// ตัวอย่างเช่น:
// this.myService.updateItem(id, updatedText).subscribe(response => {
// this.showSuccessEdit(); // เรียกฟังก์ชันแจ้งเตือน
// });
}
// เมื่อหน้าเว็บโหลดใหม่ดึงข้อมูลจาก localStorage
ngOnInit(): void {
this.items.forEach(item => {
const savedText = localStorage.getItem(`item-${item[0]}`);
if (savedText) {
item[1] = savedText; // ใช้ข้อมูลที่เก็บไว้
}
});
}
modalOptions: {
[nameModal: string]: {
isModalOpen: boolean;
modalSize: string;
backdropClose: boolean;
};
} = {
"add": { isModalOpen: false, modalSize: 'm', backdropClose: true },
"edit": { isModalOpen: false, modalSize: 'm', backdropClose: true }
};
openModal(name: string, size: string, closeOnBackdrop?: boolean) {
this.modalOptions[name].modalSize = size;
this.modalOptions[name].backdropClose = closeOnBackdrop || false;
this.modalOptions[name].isModalOpen = true;
this.currentModal = name;
document.body.style.overflow = 'hidden';
}
closeModal(name: string) {
this.modalOptions[name].isModalOpen = false;
if (!this.isAnyModalOpen()) {
document.body.style.overflow = '';
}
}
isAnyModalOpen(): boolean {
return Object.values(this.modalOptions).some(modal => modal.isModalOpen);
}
// ฟังก์ชันสำหรับการเพิ่ม ลบ หรือแก้ไข ข้อมูล
addUser() {
}
currentModal = "";
constructor(private toastr: ToastrService) { }
// แสดงข้อความแจ้งเตือนเมื่อการบันทึกสำเร็จ
showSuccessAdd() {
this.toastr.success('บันทึกข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
showSuccessEdit() {
this.toastr.success('เเก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
showSuccessDelete() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', { timeOut: 3000, positionClass: 'toast-top-right' });
}
}
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 { CompetencyGradeModel } from 'src/app/shared/model/competency-grades.model';
import { MyCompetencyGroupGradeModel } from 'src/app/shared/model/competency-group-grade.model';
import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service';
export interface DataModel { export interface DataModel {
check: boolean; check: boolean;
code: string; code: string;
tdesc: string; tdesc: string;
edesc: string; edesc: string;
competencyGrades: CompetencyGradeModel[]
} }
@Component({ @Component({
...@@ -15,41 +19,57 @@ export interface DataModel { ...@@ -15,41 +19,57 @@ export interface DataModel {
}) })
export class GradeManagementComponent { export class GradeManagementComponent {
@Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>(); @Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>();
addTab = false; typeTab: "" | "add" | "edit" = "";
editTab = false;
currentPage = 1; currentPage = 1;
page = Array.from({ length: 1 }, (_, i) => i + 1); page = Array.from({ length: 1 }, (_, i) => i + 1);
numDataListChecked = 0; numDataListChecked = 0;
isDataListChecked = false;
isDataListCheckedAll = false; isDataListCheckedAll = false;
search = ''; search = '';
dataList: DataModel[] = [ dataList: DataModel[] = [];
{ check: false, code: '01', tdesc: 'กลุ่ม 1', edesc: 'Group 1' }, dataLoading = false
{ check: false, code: '02', tdesc: 'กลุ่ม 2', edesc: 'Group 2' }, dataSelect: DataModel = { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }
{ check: false, code: '03', tdesc: 'กลุ่ม 3', edesc: 'Group 3' },
{ check: false, code: '04', tdesc: 'กลุ่ม 4', edesc: 'Group 4' },
{ check: false, code: '05', tdesc: 'กลุ่ม 5', edesc: 'Group 5' },
{ check: false, code: '06', tdesc: 'กลุ่ม 6', edesc: 'Group 6' },
{ check: false, code: '07', tdesc: 'กลุ่ม 7', edesc: 'Group 7' },
];
dataSelect: DataModel = { check: false, code: '', tdesc: '', edesc: '' }
constructor(private toastr: ToastrService) { constructor(private toastr: ToastrService,
this.pathTitleChange(); private competencyGroupGradeService: CompetencyGroupGradeService,
private cdr: ChangeDetectorRef) {
this.sendPathTitle.emit(['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด'])
}
ngOnInit(): void {
this.getCompetencyGroupGradeList()
}
selectData(data?: DataModel) {
this.dataSelect = JSON.parse(JSON.stringify(data || { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }))
}
getCompetencyGroupGradeList() {
this.dataLoading = true
this.competencyGroupGradeService.getList().subscribe({
next: response => {
this.dataList = response.map(x => ({ check: false, code: x.groupGradeId, tdesc: x.tdesc, edesc: x.edesc, competencyGrades: x.competencyGrades }))
this.dataLoading = false
this.searchChange()
this.cdr.detectChanges()
}, error: error => {
this.dataLoading = false
this.cdr.detectChanges()
}
})
}
pathTitleChange(tap?: 'add' | 'edit') {
this.typeTab = tap || ''
switch (this.typeTab) {
case 'add': {
this.sendPathTitle.emit(['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'เพิ่มกลุ่มเกรด'])
break;
}
case 'edit': {
this.sendPathTitle.emit(['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'แก้ไขกลุ่มเกรด'])
break;
}
default: {
this.sendPathTitle.emit(['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด'])
}
} }
pathTitleChange(data?: DataModel) {
this.editTab = data ? true : false
this.dataSelect = data || { check: false, code: '', tdesc: '', edesc: '' }
this.sendPathTitle.emit(
this.addTab
? ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'เพิ่มกลุ่มเกรด']
: this.editTab
? ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'แก้ไขกลุ่มเกรด']
: ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด']
);
} }
searchChange() { searchChange() {
...@@ -60,7 +80,7 @@ export class GradeManagementComponent { ...@@ -60,7 +80,7 @@ export class GradeManagementComponent {
dataListFilter() { dataListFilter() {
return this.dataList.filter((x) => { return this.dataList.filter((x) => {
const match = x.code.includes(this.search) || x.tdesc.includes(this.search); const match = x.code.toLowerCase().includes(this.search.toLowerCase()) || x.tdesc.toLowerCase().includes(this.search.toLowerCase()) || x.edesc.toLowerCase().includes(this.search.toLowerCase());
if (!match) x.check = false; if (!match) x.check = false;
return match; return match;
}); });
...@@ -68,7 +88,6 @@ export class GradeManagementComponent { ...@@ -68,7 +88,6 @@ export class GradeManagementComponent {
dataListCheck() { dataListCheck() {
const dataCheck = this.dataListFilter(); const dataCheck = this.dataListFilter();
this.isDataListChecked = dataCheck.some((x) => x.check);
this.isDataListCheckedAll = dataCheck.length ? dataCheck.every((x) => x.check) : false; this.isDataListCheckedAll = dataCheck.length ? dataCheck.every((x) => x.check) : false;
this.numDataListChecked = dataCheck.filter((x) => x.check).length; this.numDataListChecked = dataCheck.filter((x) => x.check).length;
} }
...@@ -76,31 +95,34 @@ export class GradeManagementComponent { ...@@ -76,31 +95,34 @@ export class GradeManagementComponent {
dataListCheckAll() { dataListCheckAll() {
this.isDataListCheckedAll = !this.isDataListCheckedAll; this.isDataListCheckedAll = !this.isDataListCheckedAll;
const selectAll = this.isDataListCheckedAll; const selectAll = this.isDataListCheckedAll;
this.dataList.forEach((x) => (x.check = selectAll)); this.dataList = this.dataList.filter((x) => {
this.dataListCheck(); // อัปเดตสถานะการเช็ก const match = x.code.toLowerCase().includes(this.search.toLowerCase()) || x.tdesc.toLowerCase().includes(this.search.toLowerCase()) || x.edesc.toLowerCase().includes(this.search.toLowerCase());
if (!match) x.check = false;
return match;
}).map((x) => ({ ...x, check: selectAll }));
this.dataListCheck();
} }
showSuccess() { showAlert(text: string, type: 'success' | 'error') {
this.toastr.success('เพิ่มผู้ใช้ใหม่สำเร็จ!', 'เเจ้งเตือน', { this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); })
}
showEdit() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
} }
showSuccessDelete() { deleteCompetencyGroupGradeList() {
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', { const body = this.dataSelect.code ? new MyCompetencyGroupGradeModel({ groupGradeId: this.dataSelect.code, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc }) : this.dataList.filter(x => x.check).map(x => new MyCompetencyGroupGradeModel({ groupGradeId: x.code, tdesc: x.tdesc, edesc: x.edesc }))
timeOut: 3000, this.competencyGroupGradeService.delete(body).subscribe({
positionClass: 'toast-top-right', next: response => {
}); if (response.success) {
this.showAlert(response.message, 'success')
this.getCompetencyGroupGradeList()
} else {
this.showAlert(response.message, 'error')
} }
}, error: error => {
addUser() { this.showAlert(error.message, 'error')
}
})
} }
} }
<div class="flex justify-between"> <div class="flex justify-between mb-10px">
<div class="flex">
<!-- Content ของ div แรก -->
<div class="flex"> <div class="flex">
<button type="button" <button type="button"
class="ti-btn text-primary hover:bg-blue-100 focus:ring-blue-500 dark:focus:ring-offset-white/10 h-10 m-0 shadow-md" class="ti-btn text-primary hover:bg-blue-100 focus:ring-blue-500 dark:focus:ring-offset-white/10 h-10 m-0 shadow-md"
(click)="onEdit()"> (click)="backTab()">
<i class="ti ti-chevron-left"></i> <i class="ti ti-chevron-left"></i>
ย้อนกลับ ย้อนกลับ
</button> </button>
<div class="text-2xl font-bold py-2 text-primary px-2"> <div class="text-2xl font-bold py-2 text-primary px-2">
เพิ่มกลุ่มเกรด {{typeTab=='add'?'เพิ่ม':'แก้ไข'}}กลุ่มเกรด
</div>
</div> </div>
</div> </div>
<div class="flex justify-end"> <div class="flex justify-end">
<div class="px-1"> <div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-success h-10 m-0 shadow-md" <button type="button" class="ti-btn ti-btn-soft-success h-10 m-0 shadow-md"
data-hs-overlay="#add-group-grade-alert-add-modal"> [ngClass]="{'ti-btn-disabled': !dataSelect.code}" data-hs-overlay="#add-group-grade-alert-add-modal"
[disabled]="!dataSelect.code">
<i class="ri-save-3-line"></i> <i class="ri-save-3-line"></i>
Save Save
</button> </button>
</div> </div>
<div class="px-1"> <div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-indigo h-10 m-0 shadow-md"> <button type="button" class="ti-btn ti-btn-soft-indigo h-10 m-0 shadow-md" (click)="clear()">
<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)">
...@@ -49,45 +47,42 @@ ...@@ -49,45 +47,42 @@
</div> </div>
<div class="body-content"> <div class="body-content">
<div class="page"> <div class="page">
<div class="border-b border-gray-200 dark:border-white/10 px-8"> <nav class="flex rtl:space-x-reverse space-x-2 border-b border-gray-200">
<nav class="flex rtl:space-x-reverse space-x-5" style="padding-top: 20px;"> <a (click)="currentTab=1"
<a class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900 active" class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900 active"
href="javascript:void(0);" id="underline-item-1" data-hs-tab="#underline-1" href="javascript:void(0);" id="card-type-item-1" data-hs-tab="#card-type-1" aria-controls="card-type-1">
aria-controls="underline-1" (click)="activeTab = 'details-add'">
รายละเอียด รายละเอียด
</a> </a>
<a class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900" <a (click)="currentTab=2"
href="javascript:void(0);" id="underline-item-2" data-hs-tab="#underline-2" class="border w-32 justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900"
aria-controls="underline-2" (click)="activeTab = 'grade-register'"> href="javascript:void(0);" id="card-type-item-2" data-hs-tab="#card-type-2" aria-controls="card-type-2">
ทะเบียนเกรด ทะเบียนเกรด
</a> </a>
</nav> </nav>
</div> <div class="pt-50px">
<div class="mt-3 px-3rem"> <div *ngIf="currentTab==1" id="card-type-1" role="tabpanel" aria-labelledby="card-type-item-1">
<div *ngIf="activeTab === 'details-add'" id="underline-1" role="tabpanel"
aria-labelledby="underline-item-1">
<div class="page px-rem"> <div class="page px-rem">
<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/4" placeholder=""> <input type="text" id="input-label" class="ti-form-input w-1/4" [(ngModel)]="dataSelect.code">
<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 w-1/2" placeholder=""> <input type="text" id="detail_th" class="ti-form-input w-1/2" [(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 w-1/2" placeholder=""> <input type="text" id="detail_eng" class="ti-form-input w-1/2" [(ngModel)]="dataSelect.edesc">
</div> </div>
</div> </div>
<div *ngIf="activeTab === 'grade-register'" id="underline-2" role="tabpanel" <div *ngIf="currentTab==2" id="card-type-2" class="hidden" role="tabpanel"
aria-labelledby="underline-item-2"> aria-labelledby="card-type-item-2">
<app-sub-grade-registration></app-sub-grade-registration> <app-sub-grade-registration [dataSelect]="dataSelect"
(sendDataSelect)="dataSelect=$event"></app-sub-grade-registration>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div id="add-group-grade-alert-add-modal" class="hs-overlay hidden ti-modal"> <div id="add-group-grade-alert-add-modal" class="hs-overlay hidden ti-modal">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] flex items-center"> <div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out h-[calc(100%-3.5rem)] flex items-center">
<div class="max-h-full overflow-hidden ti-modal-content-alert w-full"> <div class="max-h-full overflow-hidden ti-modal-content-alert w-full">
...@@ -105,7 +100,7 @@ ...@@ -105,7 +100,7 @@
</div> </div>
<div class="ti-modal-body "> <div class="ti-modal-body ">
<p class="mt-1 text-gray-800 dark:text-white/70"> <p class="mt-1 text-gray-800 dark:text-white/70">
ยืนยันการเพิ่มข้อมูลหรือไม่! ยืนยันการบันทึกข้อมูลหรือไม่
</p> </p>
<div class="flex justify-end mt-2rem mb-1rem"> <div class="flex justify-end mt-2rem mb-1rem">
...@@ -115,7 +110,7 @@ ...@@ -115,7 +110,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="#add-group-grade-alert-add-modal" (click)="addUser();showSuccessAdd()"> data-hs-overlay="#add-group-grade-alert-add-modal" (click)="postCompetencyGroupGrade()">
เพิ่มข้อมูล เพิ่มข้อมูล
</a> </a>
</div> </div>
......
import { Component, EventEmitter, Input, Output, OnInit, ChangeDetectorRef } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { CompetencyGradeModel } from 'src/app/shared/model/competency-grades.model';
import { MyCompetencyGroupGradeModel } from 'src/app/shared/model/competency-group-grade.model';
import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service';
export interface DataModel {
check: boolean
code: string
tdesc: string
edesc: string
competencyGrades: CompetencyGradeModel[]
}
@Component({
selector: 'app-group-grade',
templateUrl: './group-grade.component.html',
styleUrls: ['./group-grade.component.scss']
})
export class GroupGradeComponent implements OnInit {
@Output() sendBackTab: EventEmitter<undefined> = new EventEmitter<undefined>();
@Input() typeTab: 'add' | 'edit' = 'add'
@Input() dataSelect: DataModel = { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }
dataOriginal: DataModel = { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }
@Output() sendDataList: EventEmitter<DataModel[]> = new EventEmitter<DataModel[]>();
currentTab = 1
constructor(private toastr: ToastrService,
private competencyGroupGradeService: CompetencyGroupGradeService,
private cdr: ChangeDetectorRef) { }
ngOnInit(): void {
this.dataOriginal = JSON.parse(JSON.stringify(this.dataSelect || { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }))
}
clear() {
this.dataSelect = JSON.parse(JSON.stringify(this.dataOriginal || { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }))
}
backTab() {
this.sendBackTab.emit();
}
postCompetencyGroupGrade() {
this.competencyGroupGradeService.post(new MyCompetencyGroupGradeModel({ groupGradeId: this.dataSelect.code, tdesc: this.dataSelect.tdesc, edesc: this.dataSelect.edesc, competencyGrades: this.dataSelect.competencyGrades })).subscribe({
next: response => {
if (response.success) {
this.showAlert(response.message, 'success')
this.getCompetencyGroupGradeList()
} else {
this.showAlert(response.message, 'error')
}
}, error: error => {
this.showAlert(error.message, 'error')
}
})
}
getCompetencyGroupGradeList() {
this.competencyGroupGradeService.getList().subscribe({
next: response => {
this.sendDataList.emit(response.map(x => ({ check: false, code: x.groupGradeId, tdesc: x.tdesc, edesc: x.edesc, competencyGrades: x.competencyGrades })))
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000,
positionClass: 'toast-top-right',
});
}
}
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 { CompetencyGradeModel, MyCompetencyGradeModel } from 'src/app/shared/model/competency-grades.model';
import { MyCompetencyGroupGradeModel } from 'src/app/shared/model/competency-group-grade.model';
import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service';
export interface DataModel { export interface DataModel {
check: boolean; check: boolean
code: string; code: string
details: string; tdesc: string
grade: string; edesc: string
highscore: string; competencyGrades: CompetencyGradeModel[]
lowscore: string;
weight: string;
} }
@Component({ @Component({
...@@ -17,49 +18,38 @@ export interface DataModel { ...@@ -17,49 +18,38 @@ export interface DataModel {
styleUrls: ['./sub-grade-registration.component.scss'], styleUrls: ['./sub-grade-registration.component.scss'],
}) })
export class SubGradeRegistrationComponent { export class SubGradeRegistrationComponent {
@Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>(); @Input() dataSelect: DataModel = { check: false, code: '', tdesc: '', edesc: '', competencyGrades: [] }
modalStatus: "add" | "edit" = "add" @Output() sendDataSelect: EventEmitter<DataModel> = new EventEmitter<DataModel>();
addTab = false; competencyGrade: { select: CompetencyGradeModel, dataList: { check: boolean, data: CompetencyGradeModel }[] } = { select: new MyCompetencyGradeModel({}), dataList: [] }
editTab = false;
currentPage = 1; currentPage = 1;
page = Array.from({ length: 1 }, (_, i) => i + 1); page = Array.from({ length: 1 }, (_, i) => i + 1);
numDataListChecked = 0; numDataListChecked = 0;
isDataListChecked = false;
isDataListCheckedAll = false; isDataListCheckedAll = false;
search = ''; search = '';
modalStatus: 'add' | 'edit' | 'delete' = 'add'
dataList: DataModel[] = [ constructor(private toastr: ToastrService,
{ check: false, code: '01A', details: 'ระดับ A', grade: 'A', highscore: '100', lowscore: '80', weight: '1' }, private competencyGroupGradeService: CompetencyGroupGradeService,
{ check: false, code: '01B', details: 'ระดับ B', grade: 'B', highscore: '79', lowscore: '70', weight: '1' }, private cdr: ChangeDetectorRef
{ check: false, code: '01C', details: 'ระดับ C', grade: 'C', highscore: '69', lowscore: '60', weight: '1' }, ) {
{ check: false, code: '01D', details: 'ระดับ D', grade: 'D', highscore: '59', lowscore: '50', weight: '1' },
{ check: false, code: '01F', details: 'ระดับ F', grade: 'F', highscore: '49', lowscore: '0', weight: '1' },
];
constructor(private toastr: ToastrService) {
this.pathTitleChange();
} }
ngOnInit(): void {
pathTitleChange() { this.competencyGrade.dataList = this.dataSelect.competencyGrades.map(x => ({ check: false, data: x }))
this.sendPathTitle.emit( this.searchChange()
this.addTab
? ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'เพิ่มกลุ่มเกรด']
: this.editTab
? ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด', 'แก้ไขกลุ่มเกรด']
: ['การประเมินสมรรถนะ', 'ทะเบียนเกรด', 'การจัดการเกรด']
);
} }
searchChange() { searchChange() {
this.currentPage = 1; this.currentPage = 1;
const filteredData = this.dataListFilter(); const filteredData = this.dataListFilter();
this.page = Array.from({ length: Math.ceil(filteredData.length / 10) }, (_, i) => i + 1); this.page = Array.from({ length: Math.ceil(filteredData.length / 10) }, (_, i) => i + 1);
} }
selectData(data?: { check: boolean, data: CompetencyGradeModel }) {
this.competencyGrade.select = new MyCompetencyGradeModel(data?.data || {})
}
dataListFilter() { dataListFilter() {
return this.dataList.filter((x) => { return this.competencyGrade.dataList.filter((x) => {
const match = x.code.includes(this.search) || x.details.includes(this.search); const data = x.data
const match = data.gradeId.toLowerCase().includes(this.search.toLowerCase()) || data.tdesc.toLowerCase().includes(this.search.toLowerCase()) || data.edesc.toLowerCase().includes(this.search.toLowerCase());
if (!match) x.check = false; if (!match) x.check = false;
return match; return match;
}); });
...@@ -67,38 +57,47 @@ export class SubGradeRegistrationComponent { ...@@ -67,38 +57,47 @@ export class SubGradeRegistrationComponent {
dataListCheck() { dataListCheck() {
const dataCheck = this.dataListFilter(); const dataCheck = this.dataListFilter();
this.isDataListChecked = dataCheck.some((x) => x.check); this.isDataListCheckedAll = dataCheck.length ? dataCheck.every(x => x.check) : false;
this.isDataListCheckedAll = dataCheck.length ? dataCheck.every((x) => x.check) : false;
this.numDataListChecked = dataCheck.filter((x) => x.check).length; this.numDataListChecked = dataCheck.filter((x) => x.check).length;
} }
dataListCheckAll() { dataListCheckAll() {
this.isDataListCheckedAll = !this.isDataListCheckedAll;
const selectAll = this.isDataListCheckedAll; const selectAll = this.isDataListCheckedAll;
this.dataList.forEach((x) => (x.check = selectAll)); this.competencyGrade.dataList = this.competencyGrade.dataList.filter((x) => {
this.dataListCheck(); // อัปเดตสถานะการเช็ก const data = x.data
const match = data.gradeId.toLowerCase().includes(this.search.toLowerCase()) || data.tdesc.toLowerCase().includes(this.search.toLowerCase()) || data.edesc.toLowerCase().includes(this.search.toLowerCase());
if (!match) x.check = false;
return match;
}).map(x => ({ ...x, check: selectAll }));
this.dataListCheck();
} }
updateCompetencyGroupGrade() {
showSuccessAdd() { switch (this.modalStatus) {
this.toastr.success('เพิ่มข้อมูลสำเร็จ!', 'เเจ้งเตือน', { case 'add': {
timeOut: 3000, this.competencyGrade.dataList.push({ check: false, data: this.competencyGrade.select })
positionClass: 'toast-top-right', this.cdr.detectChanges()
}); break
} }
showSuccessEdit() { case 'edit': {
this.toastr.success('แก้ไขข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.competencyGrade.dataList = this.competencyGrade.dataList.map(x => x.data.gradeId == this.competencyGrade.select.gradeId ? { check: false, data: this.competencyGrade.select } : x)
timeOut: 3000, this.cdr.detectChanges()
positionClass: 'toast-top-right', break
});
} }
case 'delete': {
showSuccessDelete() { this.competencyGrade.dataList = this.competencyGrade.select.gradeId ? this.competencyGrade.dataList.filter(x => x.data.gradeId != this.competencyGrade.select.gradeId) : this.competencyGrade.dataList.filter(x => !x.check)
this.toastr.success('ลบข้อมูลสำเร็จ', 'เเจ้งเตือน', { this.cdr.detectChanges()
break
}
}
this.sendDataSelect.emit({ ...this.dataSelect, competencyGrades: this.competencyGrade.dataList.map(x => x.data) })
}
showAlert(text: string, type: 'success' | 'error') {
this.toastr[type](text, 'แจ้งเตือน', {
timeOut: 3000, timeOut: 3000,
positionClass: 'toast-top-right', positionClass: 'toast-top-right',
}); });
} }
addUser() {
}
} }
...@@ -10,22 +10,22 @@ ...@@ -10,22 +10,22 @@
<nav class="-mb-0.5 flex space-x-6 rtl:space-x-reverse"> <nav class="-mb-0.5 flex space-x-6 rtl:space-x-reverse">
<a class="text-base font-medium hs-tab-active:border-secondary hs-tab-active:text-secondary pb-3 inline-flex items-center gap-2 border-b-[3px] border-transparent whitespace-nowrap text-gray-500 dark:text-white/70 hover:text-secondary active" <a class="text-base font-medium hs-tab-active:border-secondary hs-tab-active:text-secondary pb-3 inline-flex items-center gap-2 border-b-[3px] border-transparent whitespace-nowrap text-gray-500 dark:text-white/70 hover:text-secondary active"
href="javascript:void(0);" id="underline-item-1" data-hs-tab="#underline-1" href="javascript:void(0);" id="underline-item-1" data-hs-tab="#underline-1"
aria-controls="underline-1" (click)="pathTitle = ['การประเมินสมรรถนะ','ทะเบียนกำหนดชื่อ','ประเภทสมรรถนะ']"> aria-controls="underline-1" (click)=" currentPage = 1;pathTitle = ['การประเมินสมรรถนะ','ทะเบียนกำหนดชื่อ','ประเภทสมรรถนะ']">
ประเภทสมรรถนะ ประเภทสมรรถนะ
</a> </a>
<a class="text-base font-medium hs-tab-active:border-secondary hs-tab-active:text-secondary pb-3 inline-flex items-center gap-2 border-b-[3px] border-transparent whitespace-nowrap text-gray-500 dark:text-white/70 hover:text-secondary" <a class="text-base font-medium hs-tab-active:border-secondary hs-tab-active:text-secondary pb-3 inline-flex items-center gap-2 border-b-[3px] border-transparent whitespace-nowrap text-gray-500 dark:text-white/70 hover:text-secondary"
href="javascript:void(0);" id="underline-item-2" data-hs-tab="#underline-2" href="javascript:void(0);" id="underline-item-2" data-hs-tab="#underline-2"
aria-controls="underline-2" (click)="pathTitle = ['การประเมินสมรรถนะ','ทะเบียนกำหนดชื่อ','หัวข้อสมรรถนะ']"> aria-controls="underline-2" (click)="currentPage = 2;pathTitle = ['การประเมินสมรรถนะ','ทะเบียนกำหนดชื่อ','หัวข้อสมรรถนะ']">
หัวข้อสมรรถนะ หัวข้อสมรรถนะ
</a> </a>
</nav> </nav>
</div> </div>
<div class="mt-3 px-3rem !-mt-3 pt-50px"> <div class="mt-3 px-3rem !-mt-3 pt-50px">
<div id="underline-1" role="tabpanel" aria-labelledby="underline-item-1"> <div *ngIf="currentPage == 1" id="underline-1" role="tabpanel" aria-labelledby="underline-item-1">
<app-type-registration [pathTitle]="pathTitle" <app-type-registration [pathTitle]="pathTitle"
(sendPathTitle)="pathTitle=$event"></app-type-registration> (sendPathTitle)="pathTitle=$event"></app-type-registration>
</div> </div>
<div id="underline-2" class="hidden" role="tabpanel" aria-labelledby="underline-item-2"> <div *ngIf="currentPage == 2" id="underline-2" class="hidden" role="tabpanel" aria-labelledby="underline-item-2">
<app-competency-topic [pathTitle]="pathTitle" <app-competency-topic [pathTitle]="pathTitle"
(sendPathTitle)="pathTitle=$event"></app-competency-topic> (sendPathTitle)="pathTitle=$event"></app-competency-topic>
</div> </div>
......
...@@ -7,4 +7,5 @@ import { Component } from '@angular/core'; ...@@ -7,4 +7,5 @@ import { Component } from '@angular/core';
}) })
export class NameRegistrationComponent { export class NameRegistrationComponent {
pathTitle = ['การประเมินสมรรถนะ', 'ทะเบียนกำหนดชื่อ','ประเภทสมรรถนะ'] pathTitle = ['การประเมินสมรรถนะ', 'ทะเบียนกำหนดชื่อ','ประเภทสมรรถนะ']
currentPage = 1
} }
...@@ -104,8 +104,7 @@ import { EvaluationFactorsComponent } from '../performance-management-evaluation ...@@ -104,8 +104,7 @@ import { EvaluationFactorsComponent } from '../performance-management-evaluation
import { DefineEvaluationFactorsComponent } from '../performance-management-evaluation/evaluation-factors/define-evaluation-factors/define-evaluation-factors.component'; import { DefineEvaluationFactorsComponent } from '../performance-management-evaluation/evaluation-factors/define-evaluation-factors/define-evaluation-factors.component';
import { GradeRegistrationComponent } from '../competency-assessment/grade-registration/grade-registration.component'; import { GradeRegistrationComponent } from '../competency-assessment/grade-registration/grade-registration.component';
import { GradeManagementComponent } from '../competency-assessment/grade-registration/grade-management/grade-management.component'; import { GradeManagementComponent } from '../competency-assessment/grade-registration/grade-management/grade-management.component';
import { AddGroupGradeComponent } from '../competency-assessment/grade-registration/grade-management/add-group-grade/add-group-grade.component'; import { GroupGradeComponent } from '../competency-assessment/grade-registration/grade-management/group-grade/group-grade.component';
import { EditGroupGradeComponent } from '../competency-assessment/grade-registration/grade-management/edit-froup-grade/edit-group-grade.component';
import { SubGradeRegistrationComponent } from '../competency-assessment/grade-registration/grade-management/sub-grade-registration/sub-grade-registration.component'; import { SubGradeRegistrationComponent } from '../competency-assessment/grade-registration/grade-management/sub-grade-registration/sub-grade-registration.component';
import { SettingPerformanceEvalutionComponent } from '../performance-management-evaluation/setting-performance-evalution/setting-performance-evalution.component'; import { SettingPerformanceEvalutionComponent } from '../performance-management-evaluation/setting-performance-evalution/setting-performance-evalution.component';
import { AssessmentSystemConfigurationComponent } from '../performance-management-evaluation/setting-performance-evalution/assessment-system-configuration/assessment-system-configuration.component'; import { AssessmentSystemConfigurationComponent } from '../performance-management-evaluation/setting-performance-evalution/assessment-system-configuration/assessment-system-configuration.component';
...@@ -122,6 +121,42 @@ import { CompetencycourseService } from 'src/app/shared/services/competencycours ...@@ -122,6 +121,42 @@ import { CompetencycourseService } from 'src/app/shared/services/competencycours
import { EmployeeService } from 'src/app/shared/services/employee.service'; import { EmployeeService } from 'src/app/shared/services/employee.service';
import { EvaluationCycleService } from 'src/app/shared/services/evaluation-cycle.service'; import { EvaluationCycleService } from 'src/app/shared/services/evaluation-cycle.service';
import { SettingAssessmentService } from 'src/app/shared/services/setting-assessment.service'; import { SettingAssessmentService } from 'src/app/shared/services/setting-assessment.service';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { NativeDateAdapter } from '@angular/material/core';
import { BranchService } from 'src/app/shared/services/่branch.service';
import { JobCodeService } from 'src/app/shared/services/่job-code.service';
import { FileService } from 'src/app/shared/services/file.service';
import { CompetencyGroupGradeService } from 'src/app/shared/services/competency-group-grade.service';
export const MY_DATE_FORMATS = {
parse: {
dateInput: 'DD-MM-YYYY', // รูปแบบที่ใช้สำหรับการแปลงวันที่จาก input
},
display: {
dateInput: 'DD-MM-YYYY', // รูปแบบที่ใช้ในการแสดงวันที่
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'DD-MM-YYYY',
monthYearA11yLabel: 'MMMM YYYY',
},
};
export class CustomDateAdapter extends NativeDateAdapter {
override format(date: Date, displayFormat: object): string {
if (typeof displayFormat === 'string' && displayFormat === 'DD-MM-YYYY') {
return `${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1)
.toString()
.padStart(2, '0')}/${date.getFullYear()}`;
} else {
return super.format(date, displayFormat);
}
}
}
@NgModule({ @NgModule({
declarations: [ declarations: [
SalesComponent, SalesComponent,
...@@ -207,8 +242,7 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess ...@@ -207,8 +242,7 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess
DefineEvaluationFactorsComponent, DefineEvaluationFactorsComponent,
GradeRegistrationComponent, GradeRegistrationComponent,
GradeManagementComponent, GradeManagementComponent,
AddGroupGradeComponent, GroupGradeComponent,
EditGroupGradeComponent,
SubGradeRegistrationComponent, SubGradeRegistrationComponent,
SettingPerformanceEvalutionComponent, SettingPerformanceEvalutionComponent,
AssessmentSystemConfigurationComponent, AssessmentSystemConfigurationComponent,
...@@ -230,6 +264,11 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess ...@@ -230,6 +264,11 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess
HttpClientModule, HttpClientModule,
FormsModule, FormsModule,
NgxDaterangepickerMd.forRoot(), NgxDaterangepickerMd.forRoot(),
MatDatepickerModule,
MatNativeDateModule,
MatInputModule,
MatFormFieldModule,
MatIconModule,
], ],
providers: [ providers: [
Bu1Service, Bu1Service,
...@@ -251,10 +290,16 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess ...@@ -251,10 +290,16 @@ import { SettingAssessmentService } from 'src/app/shared/services/setting-assess
EmployeeService, EmployeeService,
EvaluationCycleService, EvaluationCycleService,
SettingAssessmentService, SettingAssessmentService,
JobCodeService,
BranchService,
FileService,
CompetencyGroupGradeService,
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptor, useClass: HttpRequestInterceptor,
multi: true, multi: true,
},] },
{ provide: DateAdapter, useClass: CustomDateAdapter },
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS }]
}) })
export class DashboardModule { } export class DashboardModule { }
export interface BankBranchModel {
bankId: string
branchId: string
tdesc: string
edesc: string
}
export class MyBankBranchModel implements BankBranchModel {
bankId: string
branchId: string
tdesc: string
edesc: string
constructor(data: Partial<BankBranchModel>) {
this.bankId = data.bankId || ""
this.branchId = data.branchId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
}
}
export interface BankModel {
bankId: string
tdesc: string
edesc: string
bankCode: string
}
export class MyBankModel implements BankModel {
bankId: string
tdesc: string
edesc: string
bankCode: string
constructor(data: Partial<BankModel>) {
this.bankId = data.bankId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
this.bankCode = data.bankCode || ""
}
}
import { BankBranchModel, MyBankBranchModel } from "./bank-branch.model"
import { BankModel, MyBankModel } from "./bank.model"
export interface BanksModel {
employeeId: string
lineNo: string
accountId: string
bank: BankModel
bankBranch: BankBranchModel
}
export class MyBanksModel implements BanksModel {
employeeId: string
lineNo: string
accountId: string
bank: BankModel
bankBranch: BankBranchModel
constructor(data: Partial<BanksModel>) {
this.employeeId = data.employeeId || ""
this.lineNo = data.lineNo || ""
this.accountId = data.accountId || ""
this.bank = new MyBankModel(data.bank || {})
this.bankBranch = new MyBankBranchModel(data.bankBranch || {})
}
}
import { JobCodeModel, MyJobCodeModel } from "./job-code.model";
import { MyPrefixModel, PrefixModel } from "./prefix.model";
export interface BossModel {
employeeId: string
prefix: PrefixModel
fname: string
lname: string
efname: string
elname: string
empType: string
empPosition: string
job: JobCodeModel
thFullName: string
engFullName: string
}
export class MyBossModel implements BossModel {
employeeId: string
prefix: PrefixModel
fname: string
lname: string
efname: string
elname: string
empType: string
empPosition: string
job: JobCodeModel
thFullName: string
engFullName: string
constructor(data: Partial<BossModel>) {
this.employeeId = data.employeeId || ""
this.prefix = new MyPrefixModel(data.prefix || {})
this.fname = data.fname || ""
this.lname = data.lname || ""
this.efname = data.efname || ""
this.elname = data.elname || ""
this.empType = data.empType || ""
this.empPosition = data.empPosition || ""
this.job = new MyJobCodeModel(data.job || {})
this.thFullName = data.thFullName || ""
this.engFullName = data.engFullName || ""
}
}
export interface CompetencyGradeModel {
gradeId: string
companyId: string
edesc: string
tdesc: string
gradeDetail: string
gradeMaxScore: number
gradeMinScore: number
weight: number
}
export class MyCompetencyGradeModel implements CompetencyGradeModel {
gradeId: string
companyId: string
edesc: string
tdesc: string
gradeDetail: string
gradeMaxScore: number
gradeMinScore: number
weight: number
constructor(data: Partial<CompetencyGradeModel>) {
this.gradeId = data.gradeId || ""
this.companyId = data.companyId || ""
this.edesc = data.edesc || ""
this.tdesc = data.tdesc || ""
this.gradeDetail = data.gradeDetail || ""
this.gradeMaxScore = data.gradeMaxScore ?? 0
this.gradeMinScore = data.gradeMinScore ?? 0
this.weight = data.weight ?? 0
}
}
import { CompetencyGradeModel, MyCompetencyGradeModel } from "./competency-grades.model"
export interface CompetencyGroupGradeModel {
groupGradeId: string
companyId: string
edesc: string
tdesc: string
competencyGrades: CompetencyGradeModel[]
}
export class MyCompetencyGroupGradeModel implements CompetencyGroupGradeModel {
groupGradeId: string
companyId: string
edesc: string
tdesc: string
competencyGrades: CompetencyGradeModel[]
constructor(data: Partial<CompetencyGroupGradeModel>) {
this.groupGradeId = data.groupGradeId || ""
this.companyId = data.companyId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
this.competencyGrades = data.competencyGrades?.map(x => (new MyCompetencyGradeModel(x))) || []
}
}
export interface CostcenterModel{
costcenterId: string
tdesc: string
edesc: string
mainCostCenterCode: string
}
export class MyCostcenterModel implements CostcenterModel {
costcenterId: string
tdesc: string
edesc: string
mainCostCenterCode: string
constructor(data: Partial<CostcenterModel>) {
this.costcenterId = data.costcenterId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
this.mainCostCenterCode = data.mainCostCenterCode || ""
}
}
export interface EmpTypeModel{ export interface EmpTypeModel {
[x: string]: any; [x: string]: any;
codeId: string; codeId: string;
tdesc: string; tdesc: string;
......
import { AgeModel, MyAgeModel } from "./age.model" import { AgeModel, MyAgeModel } from "./age.model"
import { BanksModel, MyBanksModel } from "./banks.model"
import { BossModel, MyBossModel } from "./boss.model"
import { BranchModel, MyBranchModel } from "./branch.model"
import { Bu1Model, MyBu1Model } from "./bu1.model"
import { Bu2Model, MyBu2Model } from "./bu2.model"
import { Bu3Model, MyBu3Model } from "./bu3.model"
import { Bu4Model, MyBu4Model } from "./bu4.model"
import { Bu5Model, MyBu5Model } from "./bu5.model"
import { Bu6Model, MyBu6Model } from "./bu6.model"
import { Bu7Model, MyBu7Model } from "./bu7.model"
import { CostcenterModel, MyCostcenterModel } from "./costcenter.model"
import { EmpGroupModel, MyEmpGroupModel } from "./emp-group.model"
import { EmpTypeModel, MyEmpTypeModel } from "./employee-type.model"
import { JobCodeModel, MyJobCodeModel } from "./job-code.model" import { JobCodeModel, MyJobCodeModel } from "./job-code.model"
import { MyNationalModel, NationalModel } from "./national.model" import { MyNationalModel, NationalModel } from "./national.model"
import { MyNationalityModel, NationalityModel } from "./nationality.model" import { MyNationalityModel, NationalityModel } from "./nationality.model"
...@@ -6,7 +19,10 @@ import { MyPLModel, PLModel } from "./pl.model" ...@@ -6,7 +19,10 @@ import { MyPLModel, PLModel } from "./pl.model"
import { MyPositionModel, PositionModel } from "./position.model" import { MyPositionModel, PositionModel } from "./position.model"
import { MyPrefixModel, PrefixModel } from "./prefix.model" import { MyPrefixModel, PrefixModel } from "./prefix.model"
import { MyReligionModel, ReligionModel } from "./religion.model" import { MyReligionModel, ReligionModel } from "./religion.model"
import { MySalatypeModel, SalatypeModel } from "./salatype.model"
import { MyStatusModel, StatusModel } from "./status.model" import { MyStatusModel, StatusModel } from "./status.model"
import { MyTime0Model, Time0Model } from "./time0.model"
import { MyWorkareaModel, WorkareaModel } from "./workarea.model"
export interface EmployeeModel { export interface EmployeeModel {
employeeId: string employeeId: string
...@@ -46,6 +62,54 @@ export interface EmployeeModel { ...@@ -46,6 +62,54 @@ export interface EmployeeModel {
position: PositionModel position: PositionModel
jobCode: JobCodeModel jobCode: JobCodeModel
personalLevel: PLModel personalLevel: PLModel
companyId: string
idExpireDate: string
passportNo: string
passportExpireDate: string
bossId: string
boss: BossModel
bu1: Bu1Model
bu2: Bu2Model
bu3: Bu3Model
bu4: Bu4Model
bu5: Bu5Model
bu6: Bu6Model
bu7: Bu7Model
empGroup: EmpGroupModel
firstHireDate: string
startDate: string
ageWork: AgeModel
empType: EmpTypeModel
time0: Time0Model
publicHoliday: string
proDate: string
proEvery: string
approveDate: string
workarea: WorkareaModel
telExt: string
costcenter: CostcenterModel
branch: BranchModel
zeemeLogOnName: string
salatype: SalatypeModel
effSalatype: string
salary: string
empEvery: string
curchgincDate: string
receiverBankNo: string
receiverBank: string
receiverBankBranch: string
banks: BanksModel[]
taxTable: string
compenTaxTable: string
idTax: string
calTax: string
fixTax: string
calSoc: string
calPvf: string
taxMethodAct: string
ssoFlag: string
thFullName: string
engFullName: string
} }
export class MyEmployeeModel implements EmployeeModel { export class MyEmployeeModel implements EmployeeModel {
...@@ -86,6 +150,54 @@ export class MyEmployeeModel implements EmployeeModel { ...@@ -86,6 +150,54 @@ export class MyEmployeeModel implements EmployeeModel {
position: PositionModel position: PositionModel
jobCode: JobCodeModel jobCode: JobCodeModel
personalLevel: PLModel personalLevel: PLModel
companyId: string
idExpireDate: string
passportNo: string
passportExpireDate: string
bossId: string
boss: BossModel
bu1: Bu1Model
bu2: Bu2Model
bu3: Bu3Model
bu4: Bu4Model
bu5: Bu5Model
bu6: Bu6Model
bu7: Bu7Model
empGroup: EmpGroupModel
firstHireDate: string
startDate: string
ageWork: AgeModel
empType: EmpTypeModel
time0: Time0Model
publicHoliday: string
proDate: string
proEvery: string
approveDate: string
workarea: WorkareaModel
telExt: string
costcenter: CostcenterModel
branch: BranchModel
zeemeLogOnName: string
salatype: SalatypeModel
effSalatype: string
salary: string
empEvery: string
curchgincDate: string
receiverBankNo: string
receiverBank: string
receiverBankBranch: string
banks: BanksModel[]
taxTable: string
compenTaxTable: string
idTax: string
calTax: string
fixTax: string
calSoc: string
calPvf: string
taxMethodAct: string
ssoFlag: string
thFullName: string
engFullName: string
constructor(data: Partial<EmployeeModel>) { constructor(data: Partial<EmployeeModel>) {
this.employeeId = data.employeeId || "" this.employeeId = data.employeeId || ""
this.prefix = new MyPrefixModel(data.prefix || {}) this.prefix = new MyPrefixModel(data.prefix || {})
...@@ -124,6 +236,54 @@ export class MyEmployeeModel implements EmployeeModel { ...@@ -124,6 +236,54 @@ export class MyEmployeeModel implements EmployeeModel {
this.position = new MyPositionModel(data.position || {}) this.position = new MyPositionModel(data.position || {})
this.jobCode = new MyJobCodeModel(data.jobCode || {}) this.jobCode = new MyJobCodeModel(data.jobCode || {})
this.personalLevel = new MyPLModel(data.personalLevel || {}) this.personalLevel = new MyPLModel(data.personalLevel || {})
this.companyId = data.companyId || ""
this.idExpireDate = data.idExpireDate || ""
this.passportNo = data.passportNo || ""
this.passportExpireDate = data.passportExpireDate || ""
this.bossId = data.bossId || ""
this.boss = new MyBossModel(data.boss || {})
this.bu1 = new MyBu1Model(data.bu1 || {})
this.bu2 = new MyBu2Model(data.bu2 || {})
this.bu3 = new MyBu3Model(data.bu3 || {})
this.bu4 = new MyBu4Model(data.bu4 || {})
this.bu5 = new MyBu5Model(data.bu5 || {})
this.bu6 = new MyBu6Model(data.bu6 || {})
this.bu7 = new MyBu7Model(data.bu7 || {})
this.empGroup = new MyEmpGroupModel(data.empGroup || {})
this.firstHireDate = data.firstHireDate || ""
this.startDate = data.startDate || ""
this.ageWork = new MyAgeModel(data.ageWork || {})
this.empType = new MyEmpTypeModel(data.empType || {})
this.time0 = new MyTime0Model(data.time0 || {})
this.publicHoliday = data.publicHoliday || ""
this.proDate = data.proDate || ""
this.proEvery = data.proEvery || ""
this.approveDate = data.approveDate || ""
this.workarea = new MyWorkareaModel(data.workarea || {})
this.telExt = data.telExt || ""
this.costcenter = new MyCostcenterModel(data.costcenter || {})
this.branch = new MyBranchModel(data.branch || {})
this.zeemeLogOnName = data.zeemeLogOnName || ""
this.salatype = new MySalatypeModel(data.salatype || {})
this.effSalatype = data.effSalatype || ""
this.salary = data.salary || ""
this.empEvery = data.empEvery || ""
this.curchgincDate = data.curchgincDate || ""
this.receiverBankNo = data.receiverBankNo || ""
this.receiverBank = data.receiverBank || ""
this.receiverBankBranch = data.receiverBankBranch || ""
this.banks = data.banks?.map(x => new MyBanksModel(x)) || []
this.taxTable = data.taxTable || ""
this.compenTaxTable = data.compenTaxTable || ""
this.idTax = data.idTax || ""
this.calTax = data.calTax || ""
this.fixTax = data.fixTax || ""
this.calSoc = data.calSoc || ""
this.calPvf = data.calPvf || ""
this.taxMethodAct = data.taxMethodAct || ""
this.ssoFlag = data.ssoFlag || ""
this.thFullName = data.thFullName || ""
this.engFullName = data.engFullName || ""
} }
} }
...@@ -30,6 +30,8 @@ export interface JobCodeModel { ...@@ -30,6 +30,8 @@ export interface JobCodeModel {
eexperience: string eexperience: string
eresponsibility: string eresponsibility: string
equalification: string equalification: string
jobObjective: string
supervisor: string
} }
export class MyJobCodeModel implements JobCodeModel { export class MyJobCodeModel implements JobCodeModel {
...@@ -54,6 +56,8 @@ export class MyJobCodeModel implements JobCodeModel { ...@@ -54,6 +56,8 @@ export class MyJobCodeModel implements JobCodeModel {
eexperience: string eexperience: string
eresponsibility: string eresponsibility: string
equalification: string equalification: string
jobObjective: string
supervisor: string
constructor(data: Partial<JobCodeModel>) { constructor(data: Partial<JobCodeModel>) {
this.jobcodeId = data.jobcodeId || "" this.jobcodeId = data.jobcodeId || ""
this.tdesc = data.tdesc || "" this.tdesc = data.tdesc || ""
...@@ -76,6 +80,8 @@ export class MyJobCodeModel implements JobCodeModel { ...@@ -76,6 +80,8 @@ export class MyJobCodeModel implements JobCodeModel {
this.eexperience = data.eexperience || "" this.eexperience = data.eexperience || ""
this.eresponsibility = data.eresponsibility || "" this.eresponsibility = data.eresponsibility || ""
this.equalification = data.equalification || "" this.equalification = data.equalification || ""
this.jobObjective = data.jobObjective || ""
this.supervisor = data.supervisor || ""
} }
} }
import { MyPageableModel, PageableModel } from "./pageable.model"
import { MySortModel, SortModel } from "./sort.model"
export interface PageModel {
content: any
pageable: PageableModel
totalElements: number
totalPages: number
last: boolean
size: number
number: number
sort: SortModel
numberOfElements: number
first: boolean
empty: boolean
}
export class MyPageModel implements PageModel {
content: any
pageable: PageableModel
totalElements: number
totalPages: number
last: boolean
size: number
number: number
sort: SortModel
numberOfElements: number
first: boolean
empty: boolean
constructor(data: Partial<PageModel>) {
this.content = data.content
this.pageable = new MyPageableModel(data.pageable || {})
this.totalElements = data.totalElements ?? 0
this.totalPages = data.totalPages ?? 0
this.last = data.last || false
this.size = data.size ?? 0
this.number = data.number ?? 0
this.sort = new MySortModel(data.sort || {})
this.numberOfElements = data.numberOfElements ?? 0
this.first = data.first || false
this.empty = data.empty || false
}
}
import { MySortModel, SortModel } from "./sort.model"
export interface PageableModel {
sort: SortModel
offset: number
pageNumber: number
pageSize: number
paged: boolean
unpaged: boolean
}
export class MyPageableModel implements PageableModel {
sort: SortModel
offset: number
pageNumber: number
pageSize: number
paged: boolean
unpaged: boolean
constructor(data: Partial<PageableModel>) {
this.sort = new MySortModel(data.sort || {})
this.offset = data.offset ?? 0
this.pageNumber = data.pageNumber ?? 0
this.pageSize = data.pageSize ?? 0
this.paged = data.paged || false
this.unpaged = data.unpaged || false
}
}
export interface ProvinceModel {
provinceId: string
longTname: string
longEname: string
}
export class MyProvinceModel implements ProvinceModel {
provinceId: string
longTname: string
longEname: string
constructor(data: Partial<ProvinceModel>) {
this.provinceId = data.provinceId || ""
this.longTname = data.longTname || ""
this.longEname = data.longEname || ""
}
}
export interface SalatypeModel {
codeId: string
tdesc: string
edesc: string
}
export class MySalatypeModel implements SalatypeModel {
codeId: string
tdesc: string
edesc: string
constructor(data: Partial<SalatypeModel>) {
this.codeId = data.codeId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
}
}
export interface SortModel {
empty: boolean
unsorted: boolean
sorted: boolean
}
export class MySortModel implements SortModel {
empty: boolean
unsorted: boolean
sorted: boolean
constructor(data: Partial<SortModel>) {
this.empty = data.empty || false
this.unsorted = data.unsorted || false
this.sorted = data.sorted || false
}
}
export interface Time0Model {
time0id: string
tdesc: string
edesc: string
stickTm: string
hourD: number
}
export class MyTime0Model implements Time0Model {
time0id: string
tdesc: string
edesc: string
stickTm: string
hourD: number
constructor(data: Partial<Time0Model>) {
this.time0id = data.time0id || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
this.stickTm = data.stickTm || ""
this.hourD = data.hourD ?? 0
}
}
import { MyProvinceModel, ProvinceModel } from "./province.model"
export interface WorkareaModel {
workareaId: string
tdesc: string
edesc: string
store: string
province: ProvinceModel
}
export class MyWorkareaModel implements WorkareaModel {
workareaId: string
tdesc: string
edesc: string
store: string
province: ProvinceModel
constructor(data: Partial<WorkareaModel>) {
this.workareaId = data.workareaId || ""
this.tdesc = data.tdesc || ""
this.edesc = data.edesc || ""
this.store = data.store || ""
this.province = new MyProvinceModel(data.province || {})
}
}
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu1Model } from '../model/bu1.model'; import { Bu1Model } from '../model/bu1.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu1Service { ...@@ -17,16 +18,16 @@ export class Bu1Service {
getById(bu1id: string): Observable<Bu1Model> { getById(bu1id: string): Observable<Bu1Model> {
return this.http.get<Bu1Model>(this.urlApi + "/" + bu1id) return this.http.get<Bu1Model>(this.urlApi + "/" + bu1id)
} }
post(body: Bu1Model) { post(body: Bu1Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu1Model) { delete(body: Bu1Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu2Model } from '../model/bu2.model'; import { Bu2Model } from '../model/bu2.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu2Service { ...@@ -17,16 +18,16 @@ export class Bu2Service {
getById(bu2id: string): Observable<Bu2Model> { getById(bu2id: string): Observable<Bu2Model> {
return this.http.get<Bu2Model>(this.urlApi + "/" + bu2id) return this.http.get<Bu2Model>(this.urlApi + "/" + bu2id)
} }
post(body: Bu2Model) { post(body: Bu2Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu2Model) { delete(body: Bu2Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu3Model } from '../model/bu3.model'; import { Bu3Model } from '../model/bu3.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ import { Bu3Model } from '../model/bu3.model'; ...@@ -17,16 +18,16 @@ import { Bu3Model } from '../model/bu3.model';
getList(): Observable<Bu3Model[]> { getList(): Observable<Bu3Model[]> {
return this.http.get<Bu3Model[]>(this.urlApi + "/lists") return this.http.get<Bu3Model[]>(this.urlApi + "/lists")
} }
post(body: Bu3Model) { post(body: Bu3Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu3Model) { delete(body: Bu3Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu4Model } from '../model/bu4.model'; import { Bu4Model } from '../model/bu4.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu4Service { ...@@ -17,16 +18,16 @@ export class Bu4Service {
getById(bu4id: string): Observable<Bu4Model> { getById(bu4id: string): Observable<Bu4Model> {
return this.http.get<Bu4Model>(this.urlApi + "/" + bu4id) return this.http.get<Bu4Model>(this.urlApi + "/" + bu4id)
} }
post(body: Bu4Model) { post(body: Bu4Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu4Model) { delete(body: Bu4Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu5Model } from '../model/bu5.model'; import { Bu5Model } from '../model/bu5.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu5Service { ...@@ -17,16 +18,16 @@ export class Bu5Service {
getById(bu5id: string): Observable<Bu5Model> { getById(bu5id: string): Observable<Bu5Model> {
return this.http.get<Bu5Model>(this.urlApi + "/" + bu5id) return this.http.get<Bu5Model>(this.urlApi + "/" + bu5id)
} }
post(body: Bu5Model) { post(body: Bu5Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu5Model) { delete(body: Bu5Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu6Model } from '../model/bu6.model'; import { Bu6Model } from '../model/bu6.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu6Service { ...@@ -17,16 +18,16 @@ export class Bu6Service {
getById(bu6id: string): Observable<Bu6Model> { getById(bu6id: string): Observable<Bu6Model> {
return this.http.get<Bu6Model>(this.urlApi + "/" + bu6id) return this.http.get<Bu6Model>(this.urlApi + "/" + bu6id)
} }
post(body: Bu6Model) { post(body: Bu6Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu6Model) { delete(body: Bu6Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Bu7Model } from '../model/bu7.model'; import { Bu7Model } from '../model/bu7.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class Bu7Service { ...@@ -17,16 +18,16 @@ export class Bu7Service {
getById(bu7id: string): Observable<Bu7Model> { getById(bu7id: string): Observable<Bu7Model> {
return this.http.get<Bu7Model>(this.urlApi + "/" + bu7id) return this.http.get<Bu7Model>(this.urlApi + "/" + bu7id)
} }
post(body: Bu7Model) { post(body: Bu7Model): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: Bu7Model) { delete(body: Bu7Model): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { AlertModel } from '../model/alert.model';
import { CompetencyGroupGradeModel } from '../model/competency-group-grade.model';
@Injectable({
providedIn: 'root'
})
export class CompetencyGroupGradeService {
api = "/competency-group-grade"
urlApi = environment.baseUrl + this.api
constructor(private http: HttpClient) {
}
getById(plId: string): Observable<CompetencyGroupGradeModel> {
return this.http.get<CompetencyGroupGradeModel>(this.urlApi + "/" + plId)
}
getList(): Observable<CompetencyGroupGradeModel[]> {
return this.http.get<CompetencyGroupGradeModel[]>(this.urlApi + "/lists")
}
post(body: CompetencyGroupGradeModel): Observable<AlertModel> {
return this.http.post<AlertModel>(this.urlApi, body)
}
delete(body: CompetencyGroupGradeModel | CompetencyGroupGradeModel[]): 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
...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { CompetencytopicModel } from '../model/competencytopic.model'; import { CompetencytopicModel } from '../model/competencytopic.model';
import { AlertModel } from '../model/alert.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +18,16 @@ export class CompetencytopicService { ...@@ -17,16 +18,16 @@ export class CompetencytopicService {
getList(): Observable<CompetencytopicModel[]> { getList(): Observable<CompetencytopicModel[]> {
return this.http.get<CompetencytopicModel[]>(this.urlApi + "/lists") return this.http.get<CompetencytopicModel[]>(this.urlApi + "/lists")
} }
post(body: CompetencytopicModel) { post(body: CompetencytopicModel): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: CompetencytopicModel) { delete(body: CompetencytopicModel | CompetencytopicModel[]): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
\ No newline at end of file
...@@ -3,6 +3,8 @@ import { Injectable } from '@angular/core'; ...@@ -3,6 +3,8 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { CompetencytypeModel } from '../model/competencytype.model'; import { CompetencytypeModel } from '../model/competencytype.model';
import { AlertModel } from '../model/alert.model';
import { EmpGroupModel } from '../model/emp-group.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -17,16 +19,16 @@ export class CompetencytypeService { ...@@ -17,16 +19,16 @@ export class CompetencytypeService {
getList(): Observable<CompetencytypeModel[]> { getList(): Observable<CompetencytypeModel[]> {
return this.http.get<CompetencytypeModel[]>(this.urlApi + "/lists") return this.http.get<CompetencytypeModel[]>(this.urlApi + "/lists")
} }
post(body: CompetencytypeModel) { post(body: CompetencytypeModel ): Observable<AlertModel> {
return this.http.post(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
delete(body: CompetencytypeModel) { delete(body: CompetencytypeModel | CompetencytypeModel[]): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
\ No newline at end of file
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { expand, map, Observable, reduce } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { EmployeeModel } from '../model/employee.model'; import { EmployeeModel } from '../model/employee.model';
import { AlertModel } from '../model/alert.model';
import { PageModel } from '../model/page.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
...@@ -11,25 +13,37 @@ export class EmployeeService { ...@@ -11,25 +13,37 @@ export class EmployeeService {
urlApi = environment.baseUrl + this.api urlApi = environment.baseUrl + this.api
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
} }
getPageList(): Observable<EmployeeModel[]> { getPageList(page: string, size: string): Observable<PageModel> {
return this.http.get<EmployeeModel[]>(this.urlApi + "/profiles") return this.http.get<PageModel>(this.urlApi + "/lists?page=" + page + "&size=" + size)
} }
getPageListAll(): Observable<EmployeeModel[]> {
return this.http.get<PageModel>(`${this.urlApi}/lists?page=0&size=100`).pipe(
expand(response =>
!response.last
? this.http.get<PageModel>(`${this.urlApi}/lists?page=${response.pageable.pageNumber + 1}&size=100`)
: []
),
map(response => response.content),
reduce((acc: EmployeeModel[], data) => [...acc, ...data], [])
);
}
getById(employeeId: string): Observable<EmployeeModel> { getById(employeeId: string): Observable<EmployeeModel> {
return this.http.get<EmployeeModel>(this.urlApi + "/profile?employeeId=" + employeeId) return this.http.get<EmployeeModel>(this.urlApi + "/profile?employeeId=" + employeeId)
} }
add(body: EmployeeModel) { add(body: EmployeeModel): Observable<AlertModel> {
return this.http.post(this.urlApi + '/profile-create', body) return this.http.post<AlertModel>(this.urlApi + '/profile-create', body)
} }
update(body: EmployeeModel) { update(body: EmployeeModel): Observable<AlertModel> {
return this.http.post(this.urlApi + '/profile-update', body) return this.http.post<AlertModel>(this.urlApi + '/profile-update', body)
} }
delete(body: EmployeeModel) { delete(body: EmployeeModel): Observable<AlertModel> {
const options = { const options = {
headers: new HttpHeaders({ headers: new HttpHeaders({
"Content-Type": "application/json", "Content-Type": "application/json",
}), }),
body: body body: body
}; };
return this.http.delete(this.urlApi, options) return this.http.delete<AlertModel>(this.urlApi, options)
} }
} }
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { AlertModel } from '../model/alert.model';
@Injectable({
providedIn: 'root'
})
export class FileService {
constructor(private http: HttpClient) {
}
upload(formData: any, table: string): Observable<AlertModel> {
return this.http.post<AlertModel>(environment.baseUrl + '/import/excel/' + table, formData)
}
download(fileName: string) {
return this.http.get("/assets/template/" + fileName, { responseType: "blob" })
}
}
...@@ -19,18 +19,6 @@ import { AlertModel } from '../model/alert.model'; ...@@ -19,18 +19,6 @@ import { AlertModel } from '../model/alert.model';
getList(): Observable<PositionModel[]> { getList(): Observable<PositionModel[]> {
return this.http.get<PositionModel[]>(this.urlApi + "/lists") return this.http.get<PositionModel[]>(this.urlApi + "/lists")
} }
// post(body: PositionModel) {
// return this.http.post(this.urlApi, body)
// }
// delete(body: PositionModel) {
// const options = {
// headers: new HttpHeaders({
// "Content-Type": "application/json",
// }),
// body: body
// };
// return this.http.delete(this.urlApi, options)
// }
post(body: PositionModel): Observable<AlertModel> { post(body: PositionModel): Observable<AlertModel> {
return this.http.post<AlertModel>(this.urlApi, body) return this.http.post<AlertModel>(this.urlApi, body)
} }
......
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { BranchModel } from '../model/branch.model';
@Injectable({
providedIn: 'root'
})
export class BranchService {
api = "/branch"
urlApi = environment.baseUrl + this.api
constructor(private http: HttpClient) {
}
getList(): Observable<BranchModel[]> {
return this.http.get<BranchModel[]>(this.urlApi + "/lists")
}
getById(branchId: string): Observable<BranchModel> {
return this.http.get<BranchModel>(this.urlApi + "/" + branchId)
}
// post(body: BranchModel): Observable<AlertModel> {
// return this.http.post<AlertModel>(this.urlApi, body)
// }
// delete(body: BranchModel | BranchModel[]): Observable<AlertModel> {
// const options = {
// headers: new HttpHeaders({
// "Content-Type": "application/json",
// }),
// body: body
// };
// return this.http.delete<AlertModel>(this.urlApi, options)
// }
}
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { JobCodeModel } from '../model/job-code.model';
@Injectable({
providedIn: 'root'
})
export class JobCodeService {
api = "/jobcode"
urlApi = environment.baseUrl + this.api
constructor(private http: HttpClient) {
}
getList(): Observable<JobCodeModel[]> {
return this.http.get<JobCodeModel[]>(this.urlApi + "/lists")
}
getById(jobcodeId: string): Observable<JobCodeModel> {
return this.http.get<JobCodeModel>(this.urlApi + "/" + jobcodeId)
}
// post(body: JobCodeModel): Observable<AlertModel> {
// return this.http.post<AlertModel>(this.urlApi, body)
// }
// delete(body: JobCodeModel | JobCodeModel[]): Observable<AlertModel> {
// const options = {
// headers: new HttpHeaders({
// "Content-Type": "application/json",
// }),
// body: body
// };
// return this.http.delete<AlertModel>(this.urlApi, options)
// }
}
...@@ -5140,6 +5140,10 @@ select option:focus { ...@@ -5140,6 +5140,10 @@ select option:focus {
border-top-left-radius: 0.5rem; border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem; border-top-right-radius: 0.5rem;
} }
.\!rounded-t-sm {
border-top-left-radius: 0.25rem !important;
border-top-right-radius: 0.25rem !important;
}
.rounded-t-sm { .rounded-t-sm {
border-top-left-radius: 0.25rem; border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem; border-top-right-radius: 0.25rem;
...@@ -24902,3 +24906,13 @@ div:where(.swal2-container) div:where(.swal2-validation-message) { ...@@ -24902,3 +24906,13 @@ div:where(.swal2-container) div:where(.swal2-validation-message) {
.\!\-mt-3 { .\!\-mt-3 {
margin-top: -0.75rem !important; margin-top: -0.75rem !important;
} }
.\!rounded-t-none {
border-top-left-radius: 0rem !important;
border-top-right-radius: 0rem !important;
}
.rounded-t-none {
border-top-left-radius: 0rem;
border-top-right-radius: 0rem;
}
\ 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