Commit ab6a54da by Natthaphat

module myjob

parent 3b0f29f8
<app-page-header [title]="'จัดการสมาชิก'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการสมาชิก'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect(1)"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาสมาชิก"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
<!-- <div>
<input class="form-control form-control" type="text" placeholder="กรองตามบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div> -->
<!-- <a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul> -->
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Username' | translate}}</th>
<th scope="col" class="text-start">{{ 'Fullname' | translate}}</th>
<th scope="col" class="text-start">{{ 'Email' | translate}}</th>
<th scope="col" class="text-start">{{ 'Mobile' | translate}}</th>
<th scope="col" class="text-start">{{ 'User Group' | translate}}</th>
<th scope="col" class="text-start">{{ 'Status' | translate}}</th>
<th scope="col" class="text-start">{{ 'Update Date' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.memberId)"
(change)="onCheckboxChange(item.memberId)" aria-label="..." value="">
</td>
<td>
<div class="flex items-center">
<span class="avatar avatar-sm p-1 me-1 bg-light !rounded-full">
<img
[src]="item.getPicture()"
alt="" id="profile-img">
</span>
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="view(item)">
{{item.username}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p>
</div>
</div>
</td>
<!-- <td>
<div class="flex">
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="view(item)"
data-hs-overlay="#modal-detail">
{{item.username}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p>
</div>
</div>
</td> -->
<td> {{item.firstName}} {{item.lastName}}</td>
<td>
<div>
<span class="block mb-1"><i
class="ri-mail-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.email}}</span>
</div>
</td>
<td>
<div>
<span class="block"><i
class="ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.phoneNumber}}</span>
</div>
</td>
<td> <span
class="badge bg-{{ item.role == 1 ? 'primary' : 'info'}} text-white">{{item.getRole()}}</span>
</td>
<td> <span
class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span>
</td>
<td><span class="badge bg-info/10 text-primary"><i
class="bi bi-clock me-1"></i>{{item.updatedAt | date : 'medium'}}</span></td>
<td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'User' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="selectModel.getPicture()" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input ng2FileSelect [uploader]="uploaderProfile" type="file" name="photo" class="absolute w-full h-full opacity-[0]" id="profile-change">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Username' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.username">
<div class="text-danger" *ngIf="!selectModel.username">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.password">
<div class="text-danger" *ngIf="!selectModel.password">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Confirm Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder="" [(ngModel)]="confirmPassword">
<div class="text-danger" *ngIf="!confirmPassword">
{{'Please fill in information' | translate}}
</div>
<div class="text-danger" *ngIf="confirmPassword && (confirmPassword != selectModel.password)">
{{'Password Not Match' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'ชื่อ' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.firstName">
<div class="text-danger" *ngIf="!selectModel.firstName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'นามสกุล' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.lastName">
<div class="text-danger" *ngIf="!selectModel.lastName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'อีเมล' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.email">
<div class="text-danger" *ngIf="!selectModel.email">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'เบอร์ติดต่อ' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.phoneNumber">
<div class="text-danger" *ngIf="!selectModel.phoneNumber">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'User Role' | translate}}</label>
<ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModel.role">
<ng-option [value]="0">{{'ผู้ใช้งานทั่วไป' | translate}}</ng-option>
<ng-option [value]="1">{{'ผู้ดูแลบริษัท' | translate}}</ng-option>
</ng-select>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="choices-multiple-remove-button2" id="choices-multiple-remove-button2" placeholder=""
[(ngModel)]="selectModel.status">
<ng-option [value]="0">{{'Unactive' | translate}}</ng-option>
<ng-option [value]="1">{{'Active' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { SharedModule } from "../../../shared/shared.module";
import { UserProfileModel } from "../../models/user.model";
import { TokenService } from "../../../shared/services/token.service";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from "../../../../environments/environment";
import { AdminService } from "../../services/admin.service";
@Component({
selector: 'app-admin-manage',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule
],
templateUrl: './admin-manage.component.html',
styleUrl: './admin-manage.component.css'
})
export class AdminManageComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
action = "new";
allSelected = false;
someSelected = false;
confirmPassword = ""
itemsList: UserProfileModel[] = []
filterList: UserProfileModel[] = []
selectedItems = new Map<string, boolean>();
selectModel: UserProfileModel = new UserProfileModel()
empList: UserProfileModel[] = []
descName = 'engName'
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private adminService: AdminService, public translate: TranslateService, private tokenService: TokenService) {
this.uploadConfig()
}
uploadConfig() {
this.uploaderProfile = new FileUploader({
url: environment.baseUrl + "/api/upload-image",
isHTML5: true,
authToken: this.tokenService.getToken()!,
});
this.uploaderProfile.onAfterAddingFile = (fileItem: FileItem) => {
fileItem.withCredentials = false;
this.uploadErrorMsg = "";
while (this.uploaderProfile!.queue.length > 1) {
this.uploaderProfile!.queue[0].remove();
}
if (fileItem.file.size > 5000000) {
this.uploadErrorMsg = "maximum file size 5mb.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
if (fileItem.file.type!.indexOf("image") === -1) {
this.uploadErrorMsg = "please upload image only.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
fileItem.upload();
};
this.uploaderProfile.onCompleteItem = (
item: FileItem,
response: string,
status: number,
headers: ParsedResponseHeaders
) => {
if (item.isSuccess) {
const res = JSON.parse(response);
console.log("res", res);
this.selectModel.picture = res.filename
swal(res.message, "บันทึกสำเร็จ", "success");
} else {
this.uploadErrorMsg = "cannot upload file.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
}
};
}
ngOnInit(): void {
this.adminService.getLists().subscribe(result => {
this.itemsList = result.filter(e => e.role == 99)
this.updatePagedItems()
})
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.memberId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.username?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.email?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.phoneNumber?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.getRole()?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.getStatus()?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.getFullname()?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: UserProfileModel) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.adminService.delete(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit()
})
}
});
}
new() {
this.action = 'add'
this.selectModel = new UserProfileModel()
}
view(item: UserProfileModel) {
this.action = 'edit'
this.confirmPassword = ''
this.selectModel = new UserProfileModel(item)
console.log(this.selectModel)
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectModel.role = 99
if (this.action == 'add') {
this.adminService.save(this.selectModel).subscribe(result => {
console.log(result)
swal("Save Success!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
} else if (this.action == 'edit') {
this.adminService.update(this.selectModel).subscribe(result => {
console.log(result)
swal("Update Success!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
}
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.memberId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.memberId));
}
onCheckboxChange(memberId: string) {
const isSelected = this.selectedItems.get(memberId) || false;
this.selectedItems.set(memberId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.memberId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.memberId));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, memberId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, memberId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
if (user) {
this.adminService.delete(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
adjustSelect(status: number) {
let title = "Are you sure?"
let employeeInfo = ''; // ตัวแปรสำหรับเก็บข้อมูลพนักงาน
this.selectedItems.forEach((isSelected, memberId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
}
});
swal({
title: title,
text: employeeInfo,
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, memberId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
if (user) {
user.status = status
this.adminService.update(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
filterEmp(empId: string) {
this.selectModel = this.empList.filter(e => e.memberId == empId)[0]
}
}
:host {
display: block;
}
.small-html {
font-size: 0.85rem; /* ลดขนาดฟอนต์ */
line-height: 1.2; /* ลดระยะบรรทัด */
max-height: 150px; /* จำกัดความสูง */
overflow-y: auto; /* ถ้าเนื้อหายาวเกิน ให้เลื่อนดูได้ */
display: block;
}
.border-radius-1{
border-radius: 0.50rem;
}
.font-14{
font-size: 14px;
}
.font-16{
font-size: 16px;
}
.font-24{
font-size: 24px;
}
.font-36{
font-size: 36px;
}
.page {
display: flex;
height: auto;
flex-direction: column;
}
.hs-tab-active {
background-color: rgb(21, 76, 156) !important;
border-color: rgb(21, 76, 156) !important;
color: #FFFFFF !important;
}
.active {
background-color: rgb(21, 76, 156) !important;
border-color: rgb(21, 76, 156) !important;
color: #FFFFFF !important;
}
.border-color{
border: 8px solid rgb(255, 255, 255);
}
.ti-btn-amber-full{
background-color: #fcd34d;
color: #FFFFFF;
}
\ No newline at end of file
<app-page-header [title]="'จัดการบทความ'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการบทความ'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
(click)="openDialog()" data-hs-overlay="#modal-detail"><i
class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect(1)"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Publish' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-amber-full ti-btn-sec me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unpublish' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">รูปภาพ</th>
<th scope="col" class="text-start">หัวข้อบทความ</th>
<th scope="col" class="text-start">ผู้เขียนบทความ</th>
<th scope="col" class="text-start">{{"Status" | translate}}</th>
<th scope="col" class="text-start">วันที่เผยเเพร่</th>
<!-- <th scope="col" class="text-start">วันที่สิ้นสุดการเผยเเพร่</th> -->
<th scope="col" class="text-start">วันที่เเก้ไขล่าสุด</th>
<!-- <th scope="col" class="text-start">{{"Update Date" | translate}}</th> -->
<th scope="col" class="text-start">การจัดการ</th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.articleId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.articleId) || false"
(change)="onCheckboxChange(item.articleId)" aria-label="...">
</td>
<td>
<div class="flex items-center">
<span class="p-3 me-1" style="width: 200px;">
<!-- <img [src]="item.getPicture()" alt="" id="profile-img" class="border-radius-1"
style="width: 180px; height: 120px; object-fit: cover;"> -->
<img [src]="item.getPicture() === '' ? 'assets/images/media/default-pic-gX.png' : item.getPicture()" id="profile-img" class="border-radius-1"
style="width: 180px; height: 120px; object-fit: cover;">
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.title}}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.author}}
</span>
</div>
</td>
<td>
<div>
<ng-container *ngIf="item.publish === 1">
<span class="badge bg-success text-white">
เผยแพร่ </span>
</ng-container>
<ng-container *ngIf="item.publish === 0">
<span class="badge bg-amber-300 text-white">
ไม่เผยแพร่ </span>
</ng-container>
</div>
</td>
<!-- <td>
<span class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">
{{item.getStatus()}}
</span>
</td> -->
<td>
<span class="badge bg-info/10 text-primary">
<i class="bi bi-clock me-1"></i>
{{item.createdDate | date : 'dd/MM/yyyy HH:mm'}}
</span>
</td>
<!-- <td>
<span class="badge bg-info/10 text-primary">
<i class="bi bi-clock me-1"></i>
{{item.endDate | date : 'dd/MM/yyyy HH:mm'}}
</span>
</td> -->
<td>
<span class="badge bg-info/10 text-primary">
<i class="bi bi-clock me-1"></i>
{{item.lastModifiedDate | date : 'dd/MM/yyyy HH:mm'}}
</span>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" (click)="openDialog()"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #articleModel let-modal>
<div class="modal-headtitle ti-modal-header flex justify-between items-center p-4" style="background-color: #fefbfb;">
<h3 class="modal-title text-sm font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }}{{ 'บทความ' | translate }}
</h3>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(click)="closeDialog()" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="w-full flex justify-end">
<div class="absolute flex">
<div class="px-1">
</div>
</div>
</div>
<mat-dialog-content style="padding: 0px; padding-left: 20px; padding-right: 20px;">
<div class="box p-9 top-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12 justify-items-center">
<div class="relative w-[300px] h-[200px] overflow-hidden rounded-md group mx-auto">
<img [src]="selectModel.getPicture() === '' ? 'assets/images/media/default-pic-gX.png' : selectModel.getPicture()"
alt="Profile Picture"
class="w-full h-full block transition-all duration-300 ease-in-out group-hover:blur-md border-color">
<div
class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-30 opacity-0 transition-opacity duration-300 ease-in-out group-hover:opacity-100 cursor-pointer"
(click)="triggerFileInput()">
<input #profileChangeInput ng2FileSelect [uploader]="uploaderProfile" type="file" name="photo"
class="hidden" id="profile-change-input">
<button
class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg opacity-100 transition-opacity duration-300 ease-in-out">
<i class="fe fe-camera text-[.625rem]"></i> Upload
</button>
</div>
</div>
</div>
<!-- <div class="xl:col-span-6 col-span-12">
<label for="articleId" class="text-primary mt-4 font-bold font-14">{{'รหัสบทความ' | translate}}</label>
<input type="text" class="form-control" id="articleId" placeholder="" [(ngModel)]="selectModel.articleId"
[readonly]="action === 'edit'" [ngClass]="{ '!bg-input-readonly': action === 'edit' }">
<div class="text-danger" *ngIf="!selectModel.articleId && action === 'add'">
{{'Please fill in information' | translate}}
</div>
</div> -->
<div class="xl:col-span-6 col-span-12">
<label for="author" class="text-primary mt-4 font-bold font-14">{{'ผู้เขียนบทความ' | translate}}</label>
<input type="text" class="form-control" id="author" placeholder="" [(ngModel)]="selectModel.author">
<div class="text-danger" *ngIf="!selectModel.author">
{{'Please fill in information' | translate}}
</div>
</div>
<!-- <div class="xl:col-span-6 col-span-12">
<label for="lastModifiedDate" class="mt-4 font-bold font-14 text-primary">{{'วันที่เเก้ไขล่าสุด' |
translate}}</label>
<input type="datetime-local" class="form-control" id="lastModifiedDate" placeholder=""
[(ngModel)]="selectModel.lastModifiedDate" [min]="selectModel.createdDate" disabled>
<div class="text-danger" *ngIf="!selectModel.lastModifiedDate">
{{'Please fill in information' | translate}}
</div>
</div> -->
<div class="xl:col-span-6 col-span-12">
<label for="createdDate" class="mt-4 font-bold font-14 text-primary">{{'วันที่เผยเเพร่' | translate}}</label>
<input type="datetime-local" class="form-control" id="createdDate" placeholder=""
[(ngModel)]="selectModel.createdDate" (ngModelChange)="updateMinDate()" max="9999-12-31T23:59">
<div class="text-danger" *ngIf="!selectModel.createdDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="endDate" class="mt-4 font-bold font-14 text-primary">{{'วันที่สิ้นสุดการเผยเเพร่' |
translate}}</label>
<input type="datetime-local" class="form-control" id="endDate" placeholder=""
[(ngModel)]="selectModel.endDate" [min]="selectModel.createdDate" max="9999-12-31T23:59">
<div class="text-danger" *ngIf="!selectModel.endDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="mt-4 font-bold font-14 text-primary" for="Detail_content">{{ "ชื่อหัวข้อบทความ" | translate }}:
<span class="text-danger">*</span></label>
<nav class="flex rtl:space-x-reverse space-x-2 border-b border-gray-200 mt-3">
<a (click)="currentarticleIdTab = 1" [class.active]="currentarticleIdTab === 1"
[class.hs-tab-active]="currentarticleIdTab === 1"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-1" aria-controls="card-type-con-content-1">
ไทย
</a>
<a (click)="currentarticleIdTab = 2" [class.active]="currentarticleIdTab === 2"
[class.hs-tab-active]="currentarticleIdTab === 2"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-2" aria-controls="card-type-con-content-2">
อังกฤษ
</a>
<a (click)="currentarticleIdTab = 3" [class.active]="currentarticleIdTab === 3"
[class.hs-tab-active]="currentarticleIdTab === 3"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-3" aria-controls="card-type-con-content-3">
จีน
</a>
</nav>
<div *ngIf="currentarticleIdTab === 1" id="card-type-con-title-1" role="tabpanel"
aria-labelledby="card-type-item-con-title-1" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.title" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.title">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentarticleIdTab === 2" id="card-type-con-titleEng-2" role="tabpanel"
aria-labelledby="card-type-item-con-titleEng-2" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.titleEng" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.titleEng">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentarticleIdTab === 3" id="card-type-con-titleChina-3" role="tabpanel"
aria-labelledby="card-type-item-con-titleChina-3" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.titleChina" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.titleChina">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
<!-- <div class="xl:col-span-6 col-span-12">
<label for="title" class="text-primary mt-4 font-bold font-14">{{'ชื่อหัวข้อบทความ' | translate}}</label>
<input type="text" class="form-control" id="title" placeholder="" [(ngModel)]="selectModel.title">
<div class="text-danger" *ngIf="!selectModel.title">
{{'Please fill in information' | translate}}
</div>
</div> -->
<!-- <div class="xl:col-span-6 col-span-12">
<label for="lastModifiedDate" class="mt-4 font-bold font-14 text-primary">{{'วันที่เเก้ไขล่าสุด' |
translate}}</label>
<input type="datetime-local" class="form-control" id="lastModifiedDate" placeholder=""
[(ngModel)]="selectModel.lastModifiedDate" [min]="selectModel.createdDate">
<div class="text-danger" *ngIf="!selectModel.lastModifiedDate">
{{'Please fill in information' | translate}}
</div>
</div> -->
<!-- ย่อความ -->
<div class="xl:col-span-12 col-span-12">
<label class="mt-4 font-bold font-14 text-primary" for="Detail_ex">{{ "บทความเเบบย่อ" | translate }}: <span
class="text-danger">*</span></label>
<nav class="flex rtl:space-x-reverse space-x-2 border-b border-gray-200 mt-3">
<a (click)="currentExcerptTab = 1" [class.active]="currentExcerptTab === 1"
[class.hs-tab-active]="currentExcerptTab === 1"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-excerpt-1" aria-controls="card-type-con-excerpt-1">
ไทย
</a>
<a (click)="currentExcerptTab = 2" [class.active]="currentExcerptTab === 2"
[class.hs-tab-active]="currentExcerptTab === 2"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-excerpt-2" aria-controls="card-type-con-excerpt-2">
อังกฤษ
</a>
<a (click)="currentExcerptTab = 3" [class.active]="currentExcerptTab === 3"
[class.hs-tab-active]="currentExcerptTab === 3"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-excerpt-3" aria-controls="card-type-con-excerpt-3">
จีน
</a>
</nav>
<div *ngIf="currentExcerptTab === 1" id="card-type-con-excerpt-1" role="tabpanel"
aria-labelledby="card-type-item-con-excerpt-1" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.excerpt" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.excerpt">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentExcerptTab === 2" id="card-type-con-excerpt-2" role="tabpanel"
aria-labelledby="card-type-item-con-excerpt-2" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.excerptEng" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.excerptEng">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentExcerptTab === 3" id="card-type-con-excerpt-3" role="tabpanel"
aria-labelledby="card-type-item-con-excerpt-3" class="" style="background-color: rgb(255, 255, 255);">
<textarea [(ngModel)]="selectModel.excerptChina" rows="5" cols="50"
style="max-height: 200px; overflow-y: auto; width: 100%;">
</textarea>
<div class="text-danger" *ngIf="!selectModel.excerptChina">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="mt-4 font-bold font-14 text-primary" for="Detail_content">{{ "เนื้อหาบทความ" | translate }}:
<span class="text-danger">*</span></label>
<nav class="flex rtl:space-x-reverse space-x-2 border-b border-gray-200 mt-3">
<a (click)="currentContentTab = 1" [class.active]="currentContentTab === 1"
[class.hs-tab-active]="currentContentTab === 1"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-1" aria-controls="card-type-con-content-1">
ไทย
</a>
<a (click)="currentContentTab = 2" [class.active]="currentContentTab === 2"
[class.hs-tab-active]="currentContentTab === 2"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-2" aria-controls="card-type-con-content-2">
อังกฤษ
</a>
<a (click)="currentContentTab = 3" [class.active]="currentContentTab === 3"
[class.hs-tab-active]="currentContentTab === 3"
class="border w-32 justify-center rounded-4px -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="card-type-item-con-content-3" aria-controls="card-type-con-content-3">
จีน
</a>
</nav>
<div *ngIf="currentContentTab === 1" id="card-type-con-content-1" role="tabpanel"
aria-labelledby="card-type-item-con-content-1" class="" style="background-color: rgb(255, 255, 255);">
<quill-editor [(ngModel)]="selectModel.content" [modules]="quillConfig"
[styles]="{'max-height': '200px','overflow-y': 'auto'}" theme="snow">
</quill-editor>
<div class="text-danger" *ngIf="!selectModel.content">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentContentTab === 2" id="card-type-con-content-2" role="tabpanel"
aria-labelledby="card-type-item-con-content-2" class="" style="background-color: rgb(255, 255, 255);">
<quill-editor [(ngModel)]="selectModel.contentEng" [modules]="quillConfig"
[styles]="{'max-height': '200px','overflow-y': 'auto'}" theme="snow">
</quill-editor>
<div class="text-danger" *ngIf="!selectModel.contentEng">
{{'Please fill in information' | translate}}
</div>
</div>
<div *ngIf="currentContentTab === 3" id="card-type-con-content-3" role="tabpanel"
aria-labelledby="card-type-item-con-content-3" class="" style="background-color: rgb(255, 255, 255);">
<quill-editor [(ngModel)]="selectModel.contentChina" [modules]="quillConfig"
[styles]="{'max-height': '200px','overflow-y': 'auto'}" theme="snow">
</quill-editor>
<div class="text-danger" *ngIf="!selectModel.contentChina">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions style="justify-content: end;">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle" data-hs-overlay="#modal-detail"
(click)="closeDialog()">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.title||!selectModel.author||!selectModel.content||!selectModel.excerpt||!selectModel.endDate"
[disabled]="!selectModel.title||!selectModel.author||!selectModel.content||!selectModel.excerpt||!selectModel.endDate">
{{'Save'| translate}}
</button>
</mat-dialog-actions>
</ng-template>
<!-- <div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'บทความ' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="selectModel.getPicture()" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input ng2FileSelect [uploader]="uploaderProfile" type="file" name="photo"
class="absolute w-full h-full opacity-[0]" id="profile-change">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="articleId" class="form-label">{{'รหัสบทความ' | translate}}</label>
<input type="text" class="form-control" id="articleId" placeholder="" [(ngModel)]="selectModel.articleId"
[readonly]="action === 'edit'" [ngClass]="{ '!bg-input-readonly': action === 'edit' }">
<div class="text-danger" *ngIf="!selectModel.articleId && action === 'add'">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="title" class="form-label">{{'ชื่อหัวข้อบทความ' | translate}}</label>
<input type="text" class="form-control" id="title" placeholder="" [(ngModel)]="selectModel.title">
<div class="text-danger" *ngIf="!selectModel.title">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="author" class="form-label">{{'ผู้เขียนบทความ' | translate}}</label>
<input type="text" class="form-control" id="author" placeholder="" [(ngModel)]="selectModel.author">
<div class="text-danger" *ngIf="!selectModel.author">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="createdDate" class="form-label">{{'วันที่สร้าง' | translate}}</label>
<input type="datetime-local" class="form-control" id="createdDate" placeholder=""
[(ngModel)]="selectModel.createdDate">
<div class="text-danger" *ngIf="!selectModel.createdDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="lastModifiedDate" class="form-label">{{'วันที่เเก้ไขล่าสุด' | translate}}</label>
<input type="datetime-local" class="form-control" id="lastModifiedDate" placeholder=""
[(ngModel)]="selectModel.lastModifiedDate">
<div class="text-danger" *ngIf="!selectModel.lastModifiedDate">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}
</button>
</div>
</div>
</div>
</div> -->
\ No newline at end of file
import { Component, ElementRef, ViewChild } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Router, RouterModule } from '@angular/router';
import { SharedModule } from '../../../shared/shared.module';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from '../../../../environments/environment';
import { TokenService } from '../../../shared/services/token.service';
import { ArticleModel } from '../../models/article.model';
import { ArticleService } from '../../services/article.service';
import { QuillModule } from 'ngx-quill';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
@Component({
selector: 'app-article-manage',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
RouterModule,
FileUploadModule,
QuillModule,
MatDialogModule,
],
templateUrl: './article-manage.component.html',
styleUrl: './article-manage.component.css',
})
export class ArticleManageComponent {
quillConfig = {
toolbar: [
['link'],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'align': [] }],
['clean'],
]
};
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild("articleModel") articleModel: any;
@ViewChild('profileChangeInput') profileChangeInputRef!: ElementRef;
dialogRef: any;
currentContentTab: number = 1;
currentExcerptTab: number = 1;
currentarticleIdTab: number = 1;
action = "new";
allSelected = false;
someSelected = false;
itemsList: ArticleModel[] = [];
filterList: ArticleModel[] = [];
selectModel: ArticleModel = new ArticleModel();
selectedItems = new Map<string, boolean>();
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(
private articleService: ArticleService,
public translate: TranslateService,
private tokenService: TokenService,
private router: Router,
private dialog: MatDialog,
) {
this.uploadConfig();
}
uploadConfig() {
this.uploaderProfile = new FileUploader({
url: environment.baseUrl + "/files/upload-image",
isHTML5: true,
authToken: this.tokenService.getToken()!,
});
this.uploaderProfile.onAfterAddingFile = (fileItem: FileItem) => {
fileItem.withCredentials = false;
this.uploadErrorMsg = "";
while (this.uploaderProfile!.queue.length > 1) {
this.uploaderProfile!.queue[0].remove();
}
if (fileItem.file.size > 5000000) {
this.uploadErrorMsg = "maximum file size 5mb.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
if (fileItem.file.type!.indexOf("image") === -1) {
this.uploadErrorMsg = "please upload image only.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
fileItem.upload();
};
this.uploaderProfile.onCompleteItem = (
item: FileItem,
response: string,
publish: number,
headers: ParsedResponseHeaders
) => {
if (item.isSuccess) {
const res = JSON.parse(response);
console.log("res", res);
this.selectModel.picture = res.resultObject;
swal(res.message, "บันทึกสำเร็จ", "success");
console.log('After Upload, selectModel is:', this.selectModel);
} else {
this.uploadErrorMsg = "cannot upload file.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
}
};
}
getArticle() {
this.articleService.getList().subscribe({
next: (response: ArticleModel[]) => {
this.itemsList = response.map((x: any) => {
const article = new ArticleModel(x, this.translate);
// แปลง createdDate
if (x.createdDate) {
article.createdDate = this.formatDateToISOString(new Date(x.createdDate));
}
// แปลง lastModifiedDate
if (x.lastModifiedDate) {
article.lastModifiedDate = this.formatDateToISOString(new Date(x.lastModifiedDate));
}
// แปลง endDate ที่มาจาก Backend (ISOZ) ให้เป็น YYYY-MM-DDTHH:mm สำหรับ Input
if (x.endDate) {
const endDateObj = new Date(x.endDate);
article.endDate = this.formatDateToISOString(endDateObj);
} else {
article.endDate = '';
}
return article;
});
console.log('ข้อมูลบทความ (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get article', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลบทความได้", "error");
}
});
}
ngOnInit(): void {
this.getArticle();
this.updateMinDate();
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.articleId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.title?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.content?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.excerpt?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.author?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.publish.toString().indexOf(v.toLowerCase()) !== -1 ||
x.endDate?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: ArticleModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.articleService.deletearticleById(item.articleId).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new ArticleModel();
this.selectModel.excerpt = "";
this.selectModel.picture = "";
this.selectModel.title = "";
this.selectModel.articleId = "";
this.selectModel.content = "";
this.selectModel.author = "";
this.selectModel.publish = 0;
const now = new Date();
this.selectModel.createdDate = this.formatDateToISOString(now);
this.selectModel.lastModifiedDate = this.formatDateToISOString(now); // ตั้งค่า lastModifiedDate เป็นเวลาปัจจุบัน (YYYY-MM-DDTHH:mm)
this.selectModel.endDate = ''; // ตั้งค่า endDate เป็น string ว่าง เพื่อให้ Input ว่างเปล่าตอนสร้างใหม่
}
view(item: ArticleModel) {
this.action = 'edit';
this.selectModel = new ArticleModel(item);
console.log(this.selectModel);
// แปลง createdDate
if (this.selectModel.createdDate) {
const createdDateObj = new Date(this.selectModel.createdDate);
this.selectModel.createdDate = this.formatDateToISOString(createdDateObj);
}
// แปลง lastModifiedDate
if (this.selectModel.lastModifiedDate) {
const lastModifiedDateObj = new Date(this.selectModel.lastModifiedDate);
this.selectModel.lastModifiedDate = this.formatDateToISOString(lastModifiedDateObj);
} else {
if (this.selectModel.createdDate) {
this.selectModel.lastModifiedDate = this.selectModel.createdDate;
}
}
// แปลง endDate ที่มาจาก Backend (ISOZ) ให้เป็น YYYY-MM-DDTHH:mm สำหรับ Input
if (this.selectModel.endDate) {
const endDateObj = new Date(this.selectModel.endDate);
this.selectModel.endDate = this.formatDateToISOString(endDateObj);
} else {
this.selectModel.endDate = '';
}
}
save() {
console.log('Before Save, selectModel is:', this.selectModel);
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willSave: any) => {
if (willSave) {
// แปลงวันที่ก่อนส่งไป Backend (ให้เป็น ISOZ) ---
let createdDateToSend: string | null = null;
if (this.selectModel.createdDate) {
createdDateToSend = new Date(this.selectModel.createdDate).toISOString();
}
let lastModifiedDateToSend: string | null = null;
if (this.selectModel.lastModifiedDate) {
lastModifiedDateToSend = new Date(this.selectModel.lastModifiedDate).toISOString();
}
let endDateToSend: string | null = null;
if (this.selectModel.endDate) {
if (this.selectModel.endDate !== '') {
endDateToSend = new Date(this.selectModel.endDate).toISOString();
}
}
const articleDataToSave: Partial<ArticleModel> = {
articleId: this.selectModel.articleId,
title: this.selectModel.title,
titleEng: this.selectModel.titleEng,
titleChina: this.selectModel.titleChina,
content: this.selectModel.content,
contentEng: this.selectModel.contentEng,
contentChina: this.selectModel.contentChina,
excerpt: this.selectModel.excerpt,
excerptEng: this.selectModel.excerptEng,
excerptChina: this.selectModel.excerptChina,
category: this.selectModel.category,
author: this.selectModel.author,
picture: this.selectModel.picture,
createdDate: createdDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
lastModifiedDate: lastModifiedDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
endDate: endDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
publish: this.selectModel.publish,
viewCount: this.selectModel.viewCount,
companyId: this.selectModel.companyId.map(company => ({
id: company.companyId,
})) as any
};
this.articleService.postArticle(articleDataToSave).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
this.updateMinDate(); // เรียกเพื่อให้ lastModifiedDate อัปเดตหลังจากบันทึก
this.closeDialog();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.articleId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.articleId));
}
onCheckboxChange(articleId: string) {
const isSelected = this.selectedItems.get(articleId) || false;
this.selectedItems.set(articleId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.articleId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.articleId));
}
deleteSelect() {
let companyInfo = '';
const selectedarticleIdsToDelete: string[] = [];
this.selectedItems.forEach((isSelected, articleId) => {
if (isSelected) {
const item = this.itemsList.find(c => c.articleId === articleId);
if (item) {
companyInfo += `${this.translate.instant('บริษัท')}: ${item.title}\n`;
selectedarticleIdsToDelete.push(item.articleId);
}
}
});
if (selectedarticleIdsToDelete.length === 0) {
swal("ข้อผิดพลาด", "กรุณาเลือกบริษัทที่ต้องการลบ", "warning");
return;
}
swal({
title: "คุณแน่ใจหรือไม่?",
text: companyInfo,
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
const deletePromises = selectedarticleIdsToDelete.map(articleId =>
this.articleService.deletearticleById(articleId).toPromise()
.then(() => true)
.catch(error => {
console.error(`Error deleting company ${articleId}:`, error);
return false;
})
);
Promise.all(deletePromises)
.then(results => {
const allSuccessful = results.every(success => success);
if (allSuccessful) {
swal("ลบสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
this.ngOnInit();
this.selectedItems.clear();
this.allSelected = false;
this.someSelected = false;
});
}
});
}
openDialog() {
this.dialogRef = this.dialog.open(this.articleModel, {
width: '1100px',
disableClose: false,
});
}
closeDialog() {
this.dialogRef.close();
}
triggerFileInput(): void {
if (this.profileChangeInputRef) {
this.profileChangeInputRef.nativeElement.click();
}
}
// ฟังก์ชันแปลง Date object เป็น YYYY-MM-DDTHH:mm สำหรับ input type="datetime-local"
private formatDateToISOString(date: Date): string {
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${year}-${month}-${day}T${hours}:${minutes}`;
}
updateMinDate() {
if (this.selectModel.createdDate) {
const created = new Date(this.selectModel.createdDate);
let modified = this.selectModel.lastModifiedDate ? new Date(this.selectModel.lastModifiedDate) : null;
if (modified && modified < created) {
this.selectModel.lastModifiedDate = this.formatDateToISOString(created);
} else if (!modified) {
this.selectModel.lastModifiedDate = this.formatDateToISOString(created);
}
}
}
adjustSelect(statusValue: number): void {
let title = "คุณแน่ใจหรือไม่?";
let articlesInfo = '';
const selectedArticles: ArticleModel[] = [];
this.selectedItems.forEach((isSelected, articleId) => {
if (isSelected) {
const article = this.itemsList.find(a => a.articleId === articleId);
if (article) {
articlesInfo += `${this.translate.instant('ชื่อบทความ')}: ${article.title}\n`;
selectedArticles.push(article);
}
}
});
if (selectedArticles.length === 0) {
swal("ข้อผิดพลาด", "กรุณาเลือกบทความที่ต้องการปรับสถานะ", "warning");
return;
}
swal({
title: title,
text: articlesInfo,
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willAdjust: any) => {
if (willAdjust) {
const updatePromises = selectedArticles.map(article => {
// แปลงวันที่ก่อนส่งไป Backend (ให้เป็น ISOZ) ---
let createdDateToSend: string | null = null;
if (article.createdDate) {
createdDateToSend = new Date(article.createdDate).toISOString();
}
let lastModifiedDateToSend: string | null = null;
if (article.lastModifiedDate) {
lastModifiedDateToSend = new Date(article.lastModifiedDate).toISOString();
}
let endDateToSend: string | null = null;
if (article.endDate) {
if (article.endDate !== '') { // ตรวจสอบว่าไม่ใช่ string ว่าง ก่อนแปลง
endDateToSend = new Date(article.endDate).toISOString();
}
}
const articleDataToSend: Partial<ArticleModel> = {
articleId: article.articleId,
title: article.title,
titleEng: article.titleEng,
titleChina: article.titleChina,
content: article.content,
contentEng: article.contentEng,
contentChina: article.contentChina,
excerpt: article.excerpt,
excerptEng: article.excerptEng,
excerptChina: article.excerptChina,
category: article.category,
author: article.author,
picture: article.picture,
createdDate: createdDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
lastModifiedDate: lastModifiedDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
endDate: endDateToSend, // <--- ใช้ค่าที่แปลงแล้ว
publish: statusValue, // อัปเดตค่า publish ที่นี่
viewCount: article.viewCount,
companyId: article.companyId.map(company => ({
id: company.companyId,
})) as any
};
return this.articleService.postArticle(articleDataToSend).toPromise()
.then(() => true)
.catch(error => {
console.error(`Error updating publish for article ${article.articleId}:`, error);
return false;
});
});
Promise.all(updatePromises)
.then(results => {
const allSuccessful = results.every(success => success);
if (allSuccessful) {
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการอัปเดตสถานะบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
this.ngOnInit();
this.selectedItems.clear();
this.allSelected = false;
this.someSelected = false;
});
}
});
}
}
\ No newline at end of file
<app-page-header [title]="'จัดการกลุ่มอาชีพ'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการกลุ่มอาชีพ'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i
class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' | translate}}</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหากลุ่มอาชีพ"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Career Cluster ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(TH)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(ENG)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Remark' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.careerClusterId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.careerClusterId) || false"
(change)="onCheckboxChange(item.careerClusterId)" aria-label="...">
</td>
<td>
<span class="block mb-1">
{{item.careerClusterId}}
</span>
</td>
<td>
<div>
<span class="block mb-1">
{{item.thName}}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.engName}}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.remark}}
</span>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Career Cluster Information' | translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Career Cluster ID' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': action === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="selectModel.careerClusterId" [readonly]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.careerClusterId">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Remark' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.remark">
<!-- <div class="text-danger" *ngIf="!selectModel.remark">
{{'Please fill in information' | translate}}
</div> -->
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.careerClusterId||!selectModel.thName||!selectModel.engName"
[disabled]="!selectModel.careerClusterId||!selectModel.thName||!selectModel.engName">{{'Save' | translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, ElementRef, ViewChild } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Router, RouterModule } from '@angular/router';
import { SharedModule } from '../../../../shared/shared.module';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from '../../../../../environments/environment';
import { TokenService } from '../../../../shared/services/token.service'
import { QuillModule } from 'ngx-quill';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { CareerClusterService } from '../../../services/career-cluster.service';
import { CareerClusterModel } from '../../../models/career-cluster.model';
@Component({
selector: 'app-career-cluster',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator,
RouterModule,
FileUploadModule,
QuillModule,
MatDialogModule
],
templateUrl: './career-cluster.component.html',
styleUrl: './career-cluster.component.css',
})
export class CareerClusterComponent {
quillConfig = {
toolbar: [
['link'], // เพิ่มปุ่มลิงก์
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'align': [] }],
['clean'], // remove formatting button
]
};
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild("CareerClusterModel") CareerClusterModel: any;
@ViewChild('profileChangeInput') profileChangeInputRef!: ElementRef;
dialogRef: any
currentContentTab: number = 1;
currentExcerptTab: number = 1;
action = "new";
allSelected = false;
someSelected = false;
itemsList: CareerClusterModel[] = [];
filterList: CareerClusterModel[] = [];
selectModel: CareerClusterModel = new CareerClusterModel();
selectedItems = new Map<string, boolean>();
// empList: CareerClusterModel[] = [];
// descName = 'engName';
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add"
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(
private careercluster: CareerClusterService,
public translate: TranslateService,
private tokenService: TokenService,
private router: Router,
private dialog: MatDialog,
) {
}
getPosition() {
this.careercluster.getList().subscribe({
next: (response: CareerClusterModel[]) => {
this.itemsList = response.map((x: any) => new CareerClusterModel(x, this.translate));
console.log('ข้อมูลตำแหน่ง (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get position', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลตำแหน่งได้", "error");
}
});
}
ngOnInit(): void {
this.getPosition();
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.careerClusterId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.remark?.toLowerCase().indexOf(v.toLowerCase()) !== -1
// x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: CareerClusterModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
const newPosition = new CareerClusterModel(item)
this.careercluster.deleteCareerCluster(newPosition).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new CareerClusterModel();
// this.selectModel.status = 1;
this.selectModel.careerClusterId = "";
this.selectModel.thName = "";
this.selectModel.engName = "";
this.selectModel.remark = "";
}
view(item: CareerClusterModel) {
this.action = 'edit';
this.selectModel = new CareerClusterModel(item);
console.log(this.selectModel);
}
save() {
console.log('Before Save, selectModel is:', this.selectModel);
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willSave: any) => {
if (willSave) {
this.careercluster.postCareerCluster(this.selectModel).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.careerClusterId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.careerClusterId));
}
onCheckboxChange(careerClusterId: string) {
const isSelected = this.selectedItems.get(careerClusterId) || false;
this.selectedItems.set(careerClusterId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.careerClusterId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.careerClusterId));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, careerClusterId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.careerClusterId === careerClusterId);
if (user) {
employeeInfo += `${this.translate.instant('thName')}: ${user.thName}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, careerClusterId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.careerClusterId === careerClusterId);
if (user) {
const newPosition = new CareerClusterModel(user)
this.careercluster.deleteCareerCluster(newPosition).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
// openDialog() {
// this.dialogRef = this.dialog.open(this.CareerClusterModel, {
// width: '1100px',
// disableClose: false,
// });
// }
// closeDialog() {
// this.dialogRef.close()
// }
}
<app-page-header [title]="'จัดการประเภทธุรกิจ'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'จัดการประเภทธุรกิจ'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาประเภท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Category ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(TH)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(ENG)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.categoryId)" (change)="onCheckboxChange(item.categoryId)"
aria-label="..." value="">
</td>
<td>
<div>
<span class="block">{{item.categoryId}}</span>
</div>
</td>
<td>
<div>
<span>{{item.thName}}</span>
</div>
</td>
<td>
<div>
<span>{{item.engName}}</span>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deletecategory(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Category' | translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Category ID' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': modalStatus === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="category.categoryId" [readonly]="modalStatus === 'edit'">
<div class="text-danger" *ngIf="!category.categoryId">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="category.thName">
<div class="text-danger" *ngIf="!category.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="category.engName">
<div class="text-danger" *ngIf="!category.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" [class.ti-btn-disabled]="!category.categoryId||!category.thName||!category.engName"
[disabled]="!category.categoryId||!category.thName||!category.engName" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { CategoryCompanyComponent } from './category-company.component';
describe('CategoryCompanyComponent', () => {
let component: CategoryCompanyComponent;
let fixture: ComponentFixture<CategoryCompanyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CategoryCompanyComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CategoryCompanyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, ElementRef, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import swal from 'sweetalert';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../../../../shared/shared.module';
import { NgSelectModule } from '@ng-select/ng-select';
import { FormsModule } from '@angular/forms';
import { MatPaginator } from '@angular/material/paginator';
import { FileUploadModule } from 'ng2-file-upload';
import { PdpaConfigComponent } from '../../pdpa-manage/pdpa-config/pdpa-config.component';
import { QuillModule } from 'ngx-quill';
import { CategoryModel } from '../../../models/category.model';
import { CategoryCompanyService } from '../../../services/category-company.service';
@Component({
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule,
QuillModule
],
selector: 'app-category-company',
templateUrl: './category-company.component.html',
styleUrls: ['./category-company.component.css']
})
export class CategoryCompanyComponent implements OnInit {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') modalDetail!: TemplateRef<any>;
currentTab = 1
allSelected = false;
someSelected = false;
itemsList: CategoryModel[] = []
filterList: CategoryModel[] = []
category: CategoryModel = new CategoryModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
modalStatus: "add" | "edit" = "add"
isSaving = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private categoryCompanyService: CategoryCompanyService, public translate: TranslateService, private modal: MatDialog) {
}
ngOnInit(): void {
this.categoryCompanyService.list().subscribe(res => {
this.itemsList = res.map(item => new CategoryModel(item, this.translate));
this.filterList = [...this.itemsList];
});
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.categoryId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
new() {
this.modalStatus = 'add'
this.category = new CategoryModel();
}
view(item: CategoryModel) {
this.modalStatus = 'edit';
this.category = new CategoryModel(item, this.translate);
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
if (this.modalStatus == 'add') {
console.log(this.category);
this.categoryCompanyService.post(this.category).subscribe(result => {
swal("Save Success!!", "บันทึกประเภทสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
} else if (this.modalStatus == 'edit') {
const respone = new CategoryModel(this.category);
this.categoryCompanyService.post(respone).subscribe(result => {
console.log(result)
swal("Update Success!!", "บันทึกประเภทสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
}
}
});
}
deletecategory(item: CategoryModel) {
const versionText = `${this.translate.instant('category')}: ${item.thName}`;
swal({
title: "Are you sure?",
text: `Confirm to delete :\n${versionText}\!`,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
}).then((willDelete: any) => {
if (willDelete) {
const res = new CategoryModel(item)
this.categoryCompanyService.delete(res).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
});
}
deleteSelect() {
let categoryConfig = '';
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const category = this.itemsList.find(category => category.categoryId === res) as CategoryModel;
if (category) {
categoryConfig += `${this.translate.instant('category')}: ${category.thName}\n`;
}
}
});
swal({
title: "Are you sure?",
text: categoryConfig,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const category = this.itemsList.find(category => category.categoryId === res);
if (category) {
const newcategory = new CategoryModel(category)
this.categoryCompanyService.delete(newcategory).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลที่เลือกสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.categoryId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.categoryId));
}
onCheckboxChange(categoryId: string) {
const isSelected = this.selectedItems.get(categoryId) || false;
this.selectedItems.set(categoryId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.categoryId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.categoryId));
}
filterEmp(empId: string) {
this.category = this.itemsList.filter(e => e.categoryId == empId)[0]
}
}
import { Component, ElementRef, ViewChild } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { SharedModule } from '../../../shared/shared.module';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-company-department',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator,
RouterModule,
],
templateUrl: './company-department.component.html',
styleUrl: './company-department.component.css',
})
export class CompanyDepartmentComponent {
ngOnInit(): void {
}
}
<app-page-header [title]="'จัดการตำแหน่ง'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการตำแหน่ง'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i
class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' | translate}}</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาตำแหน่ง"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'PositionId' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(TH)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(ENG)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Remark' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.positionId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.positionId) || false"
(change)="onCheckboxChange(item.positionId)" aria-label="...">
</td>
<td>
<span class="block mb-1">
{{item.positionId}}
</span>
</td>
<td>
<div>
<span class="block mb-1">
{{item.thName}}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.engName}}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.remark}}
</span>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Position Information' | translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'PositionId' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': action === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="selectModel.positionId" [readonly]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.positionId">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{ 'Remark' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.remark">
<!-- <div class="text-danger" *ngIf="!selectModel.remark">
{{'Please fill in information' | translate}}
</div> -->
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.positionId||!selectModel.thName||!selectModel.engName"
[disabled]="!selectModel.positionId||!selectModel.thName||!selectModel.engName">{{'Save' | translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, ElementRef, ViewChild } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Router, RouterModule } from '@angular/router';
import { SharedModule } from '../../../../shared/shared.module';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from '../../../../../environments/environment';
import { TokenService } from '../../../../shared/services/token.service'
import { QuillModule } from 'ngx-quill';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { CompanyPositionService } from '../../../services/company-position.service';
import { CompanyPositionModel } from '../../../models/company-position.model';
@Component({
selector: 'app-company-position',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator,
RouterModule,
FileUploadModule,
QuillModule,
MatDialogModule
],
templateUrl: './company-position.component.html',
styleUrl: './company-position.component.css',
})
export class CompanyPositionComponent {
quillConfig = {
toolbar: [
['link'], // เพิ่มปุ่มลิงก์
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'align': [] }],
['clean'], // remove formatting button
]
};
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild("CompanyPositionModel") CompanyPositionModel: any;
@ViewChild('profileChangeInput') profileChangeInputRef!: ElementRef;
dialogRef: any
currentContentTab: number = 1;
currentExcerptTab: number = 1;
action = "new";
allSelected = false;
someSelected = false;
itemsList: CompanyPositionModel[] = [];
filterList: CompanyPositionModel[] = [];
selectModel: CompanyPositionModel = new CompanyPositionModel();
selectedItems = new Map<string, boolean>();
// empList: CompanyPositionModel[] = [];
// descName = 'engName';
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add"
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(
private compositionservice: CompanyPositionService,
public translate: TranslateService,
private tokenService: TokenService,
private router: Router,
private dialog: MatDialog,
) {
}
getPosition() {
this.compositionservice.getList().subscribe({
next: (response: CompanyPositionModel[]) => {
this.itemsList = response.map((x: any) => new CompanyPositionModel(x, this.translate));
console.log('ข้อมูลตำแหน่ง (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get position', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลตำแหน่งได้", "error");
}
});
}
ngOnInit(): void {
this.getPosition();
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.positionId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.remark?.toLowerCase().indexOf(v.toLowerCase()) !== -1
// x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: CompanyPositionModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
const newPosition = new CompanyPositionModel(item)
this.compositionservice.deletePosition(newPosition).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new CompanyPositionModel();
// this.selectModel.status = 1;
this.selectModel.positionId = "";
this.selectModel.thName = "";
this.selectModel.engName = "";
this.selectModel.remark = "";
}
view(item: CompanyPositionModel) {
this.action = 'edit';
this.selectModel = new CompanyPositionModel(item);
console.log(this.selectModel);
}
save() {
console.log('Before Save, selectModel is:', this.selectModel);
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willSave: any) => {
if (willSave) {
this.compositionservice.postPosition(this.selectModel).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.positionId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.positionId));
}
onCheckboxChange(positionId: string) {
const isSelected = this.selectedItems.get(positionId) || false;
this.selectedItems.set(positionId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.positionId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.positionId));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, positionId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.positionId === positionId);
if (user) {
employeeInfo += `${this.translate.instant('thName')}: ${user.thName}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, positionId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.positionId === positionId);
if (user) {
const newPosition = new CompanyPositionModel(user)
this.compositionservice.deletePosition(newPosition).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
// openDialog() {
// this.dialogRef = this.dialog.open(this.CompanyPositionModel, {
// width: '1100px',
// disableClose: false,
// });
// }
// closeDialog() {
// this.dialogRef.close()
// }
}
<app-page-header [title]="'จัดการประเทศ'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'จัดการประเทศ'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Add' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาประเทศ"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Country ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(TH)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(ENG)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.countryId)" (change)="onCheckboxChange(item.countryId)"
aria-label="..." value="">
</td>
<td>
<div>
<span class="block">{{item.countryId}}</span>
</div>
</td>
<td>
<div>
<span>{{item.thName}}</span>
</div>
</td>
<td>
<div>
<span>{{item.engName}}</span>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deleteCountry(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Country' | translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Country ID' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': modalStatus === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="country.countryId" [readonly]="modalStatus === 'edit'">
<div class="text-danger" *ngIf="!country.countryId">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="country.thName">
<div class="text-danger" *ngIf="!country.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="country.engName">
<div class="text-danger" *ngIf="!country.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" [class.ti-btn-disabled]="!country.countryId||!country.thName||!country.engName"
[disabled]="!country.countryId||!country.thName||!country.engName" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { CountryRegistrationComponent } from './country-registration.component';
describe('CountryRegistrationComponent', () => {
let component: CountryRegistrationComponent;
let fixture: ComponentFixture<CountryRegistrationComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CountryRegistrationComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CountryRegistrationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, TemplateRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { Router } from "@angular/router";
import { QuillModule } from "ngx-quill";
import { MatDialog } from "@angular/material/dialog";
import { SharedModule } from "../../../../shared/shared.module";
import { PdpaConfigComponent } from "../../pdpa-manage/pdpa-config/pdpa-config.component";
import { MyPdpaModel, PdpaModel } from "../../../models/pdpa.model";
import { CountryService } from "../../../services/country.service";
import { CountryModel } from "../../../models/country.model";
@Component({
selector: 'app-country-registration',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule,
QuillModule
],
templateUrl: './country-registration.component.html',
styleUrl: './country-registration.component.css'
})
export class CountryRegistrationComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') modalDetail!: TemplateRef<any>;
currentTab = 1
allSelected = false;
someSelected = false;
itemsList: CountryModel[] = []
filterList: CountryModel[] = []
country: CountryModel = new CountryModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
modalStatus: "add" | "edit" = "add"
isSaving = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private countryService: CountryService, public translate: TranslateService, private modal: MatDialog) {
}
ngOnInit(): void {
this.countryService.list().subscribe(res => {
this.itemsList = res.map(item => new CountryModel(item, this.translate));
this.filterList = [...this.itemsList];
});
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.countryId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
new() {
this.modalStatus = 'add'
this.country = new CountryModel();
}
view(item: CountryModel) {
this.modalStatus = 'edit';
this.country = new CountryModel(item, this.translate);
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
if (this.modalStatus == 'add') {
console.log(this.country);
this.countryService.post(this.country).subscribe(result => {
swal("Save Success!!", "บันทึกประเทศสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
} else if (this.modalStatus == 'edit') {
const respone = new CountryModel(this.country);
this.countryService.post(respone).subscribe(result => {
console.log(result)
swal("Update Success!!", "บันทึกประเทศสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
}
}
});
}
deleteCountry(item: CountryModel) {
const versionText = `${this.translate.instant('Country')}: ${item.thName}`;
swal({
title: "Are you sure?",
text: `Confirm to delete :\n${versionText}\!`,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
}).then((willDelete: any) => {
if (willDelete) {
const res = new CountryModel(item)
console.log(res);
this.countryService.delete(res).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
});
}
deleteSelect() {
let countryConfig = '';
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const country = this.itemsList.find(country => country.countryId === res) as CountryModel;
if (country) {
countryConfig += `${this.translate.instant('Country')}: ${country.thName}\n`;
}
}
});
swal({
title: "Are you sure?",
text: countryConfig,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const country = this.itemsList.find(country => country.countryId === res);
if (country) {
const newCountry = new CountryModel(country)
console.log(newCountry);
this.countryService.delete(newCountry).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลที่เลือกสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.countryId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.countryId));
}
onCheckboxChange(countryId: string) {
const isSelected = this.selectedItems.get(countryId) || false;
this.selectedItems.set(countryId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.countryId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.countryId));
}
filterEmp(empId: string) {
this.country = this.itemsList.filter(e => e.countryId == empId)[0]
}
}
\ No newline at end of file
<app-page-header [title]="'จัดการระดับการศึกษา'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'จัดการระดับการศึกษา'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาระดับการศึกษา"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Degree ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(TH)' | translate}}</th>
<th scope="col" class="text-start">{{ 'Description(ENG)' | translate}}</th>
<!-- <th scope="col" class="text-start">{{ 'Higher' | translate}}</th> -->
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.degreeId)" (change)="onCheckboxChange(item.degreeId)"
aria-label="..." value="">
</td>
<td>
<div>
<span class="block">{{item.degreeId}}</span>
</div>
</td>
<td>
<div>
<span>{{item.thName}}</span>
</div>
</td>
<td>
<div>
<span>{{item.engName}}</span>
</div>
</td>
<!-- <td>
<div>
<span>{{item.higher}}</span>
</div>
</td> -->
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deletedegree(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Degree' | translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Degree ID' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': modalStatus === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="degree.degreeId" [readonly]="modalStatus === 'edit'">
<div class="text-danger" *ngIf="!degree.degreeId">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="degree.thName">
<div class="text-danger" *ngIf="!degree.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-title" class="form-label">{{'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="degree.engName">
<div class="text-danger" *ngIf="!degree.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" [class.ti-btn-disabled]="!degree.degreeId||!degree.thName||!degree.engName"
[disabled]="!degree.degreeId||!degree.thName||!degree.engName" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { DegreeManageComponent } from './degree-manage.component';
describe('DegreeManageComponent', () => {
let component: DegreeManageComponent;
let fixture: ComponentFixture<DegreeManageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DegreeManageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DegreeManageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, TemplateRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { Router } from "@angular/router";
import { QuillModule } from "ngx-quill";
import { MatDialog } from "@angular/material/dialog";
import { SharedModule } from "../../../../shared/shared.module";
import { PdpaConfigComponent } from "../../pdpa-manage/pdpa-config/pdpa-config.component";
import { MyPdpaModel, PdpaModel } from "../../../models/pdpa.model";
import { DegreeModel } from "../../../models/degree.model";
import { DegreeService } from "../../../services/degree.service";
@Component({
selector: 'app-degree-manage',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule,
QuillModule
],
templateUrl: './degree-manage.component.html',
styleUrl: './degree-manage.component.css'
})
export class DegreeManageComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') modalDetail!: TemplateRef<any>;
currentTab = 1
allSelected = false;
someSelected = false;
itemsList: DegreeModel[] = []
filterList: DegreeModel[] = []
degree: DegreeModel = new DegreeModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
modalStatus: "add" | "edit" = "add"
isSaving = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private degreeService: DegreeService, public translate: TranslateService, private modal: MatDialog) {
}
ngOnInit(): void {
this.degreeService.list().subscribe(res => {
this.itemsList = res.map(item => new DegreeModel(item, this.translate));
this.filterList = [...this.itemsList];
});
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.degreeId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.higher?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
new() {
this.modalStatus = 'add'
this.degree = new DegreeModel();
}
view(item: DegreeModel) {
this.modalStatus = 'edit';
this.degree = new DegreeModel(item, this.translate);
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
if (this.modalStatus == 'add') {
console.log(this.degree);
this.degreeService.post(this.degree).subscribe(result => {
swal("Save Success!!", "บันทึกระดับการศึกษาสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
} else if (this.modalStatus == 'edit') {
const respone = new DegreeModel(this.degree);
this.degreeService.post(respone).subscribe(result => {
console.log(result)
swal("Update Success!!", "บันทึกระดับการศึกษาสำเร็จ", "success");
this.ngOnInit()
this.childModal?.nativeElement.click()
})
}
}
});
}
deletedegree(item: DegreeModel) {
const versionText = `${this.translate.instant('degree')}: ${item.thName}`;
swal({
title: "Are you sure?",
text: `Confirm to delete :\n${versionText}\!`,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
}).then((willDelete: any) => {
if (willDelete) {
const res = new DegreeModel(item)
console.log(res);
this.degreeService.delete(res).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
});
}
deleteSelect() {
let degreeConfig = '';
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const degree = this.itemsList.find(degree => degree.degreeId === res) as DegreeModel;
if (degree) {
degreeConfig += `${this.translate.instant('degree')}: ${degree.thName}\n`;
}
}
});
swal({
title: "Are you sure?",
text: degreeConfig,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, res) => {
if (isSelected) {
const degree = this.itemsList.find(degree => degree.degreeId === res);
if (degree) {
const newdegree = new DegreeModel(degree)
console.log(newdegree);
this.degreeService.delete(newdegree).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลที่เลือกสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.degreeId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.degreeId));
}
onCheckboxChange(degreeId: string) {
const isSelected = this.selectedItems.get(degreeId) || false;
this.selectedItems.set(degreeId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.degreeId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.degreeId));
}
filterEmp(empId: string) {
this.degree = this.itemsList.filter(e => e.degreeId == empId)[0]
}
}
\ No newline at end of file
<app-page-header [title]="'จัดการประเภทงาน'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'จัดการประเภทงาน'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">รหัสประเภทงาน</th>
<th scope="col" class="text-start">รายละเอียด (ไทย)</th>
<th scope="col" class="text-start">รายละเอียด (อังกฤษ)</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.jobTypeId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.jobTypeId) || false"
(change)="onCheckboxChange(item.jobTypeId)" aria-label="...">
</td>
<td>
<div>
<span class="block mb-1">
{{item.jobTypeId}}
</span>
</div>
</td>
<td>
<span class="block mb-1">
{{item.thName}}
</span>
</td>
<td>
<span class="block mb-1">
{{item.engName}}
</span>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Company' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="jobTypeId" class="form-label">{{'JobtypeId' | translate}}</label>
<input type="text" class="form-control" id="jobTypeId" placeholder="" [(ngModel)]="selectModel.jobTypeId"
[disabled]="action === 'edit'" [readonly]="action === 'edit'"
[ngClass]="{ '!bg-input-readonly': action === 'edit' }">
<div class="text-danger" *ngIf="!selectModel.jobTypeId && action === 'add'">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="thName" class="form-label">{{'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="thName" placeholder="" [(ngModel)]="selectModel.thName"
[disabled]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="engName" class="form-label">{{'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="engName" placeholder="" [(ngModel)]="selectModel.engName"
[disabled]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.jobTypeId||!selectModel.thName||!selectModel.engName"
[disabled]="!selectModel.jobTypeId||!selectModel.thName||!selectModel.engName">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { JobTypeComponent } from './job-type.component';
describe('JobTypeComponent', () => {
let component: JobTypeComponent;
let fixture: ComponentFixture<JobTypeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ JobTypeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(JobTypeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, ElementRef, ViewChild } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../../../../shared/shared.module';
import { TokenService } from '../../../../shared/services/token.service';
import { JobTypeModel } from '../../../models/job-type.model';
import { JobTypeService } from '../../../services/job-type.service';
@Component({
selector: 'app-job-type',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator,
RouterModule,
],
templateUrl: './job-type.component.html',
styleUrl: './job-type.component.css',
})
export class JobTypeComponent {
@ViewChild("JobTypeModel") JobTypeModel: any;
dialogRef: any
currentengNameTab: number = 1;
currentExcerptTab: number = 1;
action = "new";
allSelected = false;
someSelected = false;
itemsList: JobTypeModel[] = [];
filterList: JobTypeModel[] = [];
selectModel: JobTypeModel = new JobTypeModel();
selectedItems = new Map<string, boolean>();
pageIndex = 0;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(private jobtypeservice: JobTypeService, public translate: TranslateService, private tokenService: TokenService, private router: Router,) {
}
getJobtype() {
this.jobtypeservice.getList().subscribe({
next: (response: JobTypeModel[]) => {
this.itemsList = response.map((x: any) => new JobTypeModel(x, this.translate));
console.log('ข้อมูลบริษัท (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get company', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลบริษัทได้", "error");
}
});
}
ngOnInit(): void {
this.getJobtype();
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.jobTypeId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
// x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: JobTypeModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.jobtypeservice.deleteById(item.jobTypeId).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new JobTypeModel();
this.selectModel.jobTypeId = "";
this.selectModel.thName = "";
this.selectModel.engName = "";
}
view(item: JobTypeModel) {
this.action = 'edit';
this.selectModel = new JobTypeModel(item);
}
save() {
console.log('Before Save, selectModel is:', this.selectModel);
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willSave: any) => {
if (willSave) {
this.jobtypeservice.post(this.selectModel).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.jobTypeId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.jobTypeId));
}
onCheckboxChange(jobTypeId: string) {
const isSelected = this.selectedItems.get(jobTypeId) || false;
this.selectedItems.set(jobTypeId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.jobTypeId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.jobTypeId));
}
deleteSelect() {
let companyInfo = '';
const selectedjobTypeIdsToDelete: string[] = [];
this.selectedItems.forEach((isSelected, jobTypeId) => {
if (isSelected) {
const item = this.itemsList.find(c => c.jobTypeId === jobTypeId);
if (item) {
companyInfo += `${this.translate.instant('บริษัท')}: ${item.thName}\n`;
selectedjobTypeIdsToDelete.push(item.jobTypeId);
}
}
});
if (selectedjobTypeIdsToDelete.length === 0) {
swal("ข้อผิดพลาด", "กรุณาเลือกบริษัทที่ต้องการลบ", "warning");
return;
}
swal({
title: "คุณแน่ใจหรือไม่?",
text: companyInfo,
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
const deletePromises = selectedjobTypeIdsToDelete.map(jobTypeId =>
this.jobtypeservice.deleteById(jobTypeId).toPromise()
.then(() => true)
.catch(error => {
console.error(`Error deleting company ${jobTypeId}:`, error);
return false;
})
);
Promise.all(deletePromises)
.then(results => {
const allSuccessful = results.every(success => success);
if (allSuccessful) {
swal("ลบสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
this.ngOnInit();
this.selectedItems.clear();
this.allSelected = false;
this.someSelected = false;
});
}
});
}
}
<app-page-header [title]="'จัดการจังหวัด'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการจังหวัด'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาจังหวัด"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">รหัสจังหวัด</th>
<th scope="col" class="text-start">ชื่อย่อ (ไทย)</th>
<th scope="col" class="text-start">ชื่อย่อ (อังกฤษ)</th>
<th scope="col" class="text-start">รายละเอียด (ไทย)</th>
<th scope="col" class="text-start">รายละเอียด (อังกฤษ)</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.provinceId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.provinceId) || false" (change)="onCheckboxChange(item.provinceId)"
aria-label="...">
</td>
<td>
<div>
<span class="block mb-1">
{{item.provinceId}}
</span>
</div>
</td>
<td>
<span class="block mb-1">
{{item.shortTname}}
</span>
</td>
<td>
<span class="block mb-1">
{{item.shortEname}}
</span>
</td>
<td>
<span class="block mb-1">
{{item.thName}}
</span>
</td>
<td>
<span class="block mb-1">
{{item.engName}}
</span>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Company' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="provinceId" class="form-label">{{'รหัสจังหวัด' | translate}}</label>
<input type="text" class="form-control" id="provinceId" placeholder="" [(ngModel)]="selectModel.provinceId"
[readonly]="action === 'edit'" [readonly]="action === 'edit'"
[ngClass]="{ '!bg-input-readonly': action === 'edit' }">
<div class="text-danger" *ngIf="!selectModel.provinceId && action === 'add'">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="shortTname" class="form-label">{{'ชื่อย่อ(ไทย)' | translate}}</label>
<input type="text" class="form-control" id="shortTname" placeholder="" [(ngModel)]="selectModel.shortTname">
<div class="text-danger" *ngIf="!selectModel.shortTname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="shortEname" class="form-label">{{'ชื่อย่อ(อังกฤษ)' | translate}}</label>
<input type="text" class="form-control" id="shortEname" placeholder="" [(ngModel)]="selectModel.shortEname">
<div class="text-danger" *ngIf="!selectModel.shortEname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="thName" class="form-label">{{'Description(TH)' | translate}}</label>
<input type="text" class="form-control" id="thName" placeholder="" [(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="engName" class="form-label">{{'Description(ENG)' | translate}}</label>
<input type="text" class="form-control" id="engName" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="engName" class="form-label">{{'เลือกประเทศ' | translate}}</label>
<ng-select id="countrySelect" #countrySelectRef [items]="countryList" bindLabel="thName" bindValue="this"
[(ngModel)]="selectedCountry" (change)="onCountryChange($event)" placeholder="ค้นหาหรือเลือกประเทศ"
[searchable]="true" [compareWith]="compareCountries"> <ng-template ng-header-tmp>
<input type="text" class="ti-form-input w-full form-controls"
placeholder="{{'ค้นหาประเทศ...' | translate}}"
(input)="countrySelectRef.filter($any($event.target).value)" />
</ng-template>
<ng-template ng-option-tmp let-item="item">
<div>{{item.thName}} ({{item.engName}})</div>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div>{{item.thName}}</div>
</ng-template>
</ng-select>
<div class="text-danger" *ngIf="!selectedCountry">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="region" class="form-label">{{'เลือกภูมิภาค' | translate}}</label>
<ng-select id="regionSelect" #regionSelectRef [items]="regionList" bindLabel="thName" bindValue="this"
[(ngModel)]="selectedRegion" (change)="onRegionChange($event)" placeholder="ค้นหาหรือเลือกภูมิภาค"
[searchable]="true" [compareWith]="compareRegion"> <ng-template ng-header-tmp>
<input type="text" class="ti-form-input w-full form-controls"
placeholder="{{'ค้นหาภูมิภาค...' | translate}}"
(input)="regionSelectRef.filter($any($event.target).value)" />
</ng-template>
<ng-template ng-option-tmp let-item="item">
<div>{{item.thName}} ({{item.engName}})</div>
</ng-template>
<ng-template ng-label-tmp let-item="item">
<div>{{item.thName}}</div>
</ng-template>
</ng-select>
<div class="text-danger" *ngIf="!selectedRegion">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.provinceId||!selectModel.thName||!selectModel.engName||!selectedCountry||!selectedRegion"
[disabled]="!selectModel.provinceId||!selectModel.thName||!selectModel.engName||!selectedCountry||!selectedRegion">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ProvinceComponent } from './province.component';
describe('ProvinceComponent', () => {
let component: ProvinceComponent;
let fixture: ComponentFixture<ProvinceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ProvinceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProvinceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, ElementRef, ViewChild } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../../../../shared/shared.module';
import { TokenService } from '../../../../shared/services/token.service';
import { ProvinceModel } from '../../../models/province.model';
import { ProvinceService } from '../../../services/province.service';
import { CountryModel } from '../../../models/country.model';
import { RegionModel } from '../../../models/Region.model';
import { CountryService } from '../../../services/country.service';
import { RegionService } from '../../../services/region.service';
@Component({
selector: 'app-province',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator,
RouterModule,
],
templateUrl: './province.component.html',
styleUrl: './province.component.css',
})
export class ProvinceComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild("ProvinceModel") ProvinceModel: any;
dialogRef: any
currentengNameTab: number = 1;
currentExcerptTab: number = 1;
action = "new";
allSelected = false;
someSelected = false;
itemsList: ProvinceModel[] = [];
filterList: ProvinceModel[] = [];
selectModel: ProvinceModel = new ProvinceModel();
selectedItems = new Map<string, boolean>();
countryList: CountryModel[] = [];
selectedCountry: CountryModel | undefined
regionList: RegionModel[] = []
selectedRegion: RegionModel | undefined
pageIndex = 0;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(private provinceservice: ProvinceService,
public translate: TranslateService,
private tokenService: TokenService,
private router: Router,
private countryservice: CountryService,
private regionService: RegionService,
) {
}
getJobtype() {
this.provinceservice.getList().subscribe({
next: (response: ProvinceModel[]) => {
this.itemsList = response.map((x: any) => new ProvinceModel(x, this.translate));
console.log('ข้อมูลบริษัท (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get company', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลบริษัทได้", "error");
}
});
}
getCountryList(): void {
this.countryservice.list().subscribe({
next: (response: CountryModel[]) => {
this.countryList = response;
if (this.selectModel.country && this.selectModel.country.countryId) {
this.selectedCountry = this.countryList.find(
c => c.countryId === this.selectModel.country?.countryId
);
}
},
error: (error) => {
console.error('Error fetching country list:', error);
}
});
}
getRegionList(): void {
this.regionService.getList().subscribe({
next: (response: RegionModel[]) => {
this.regionList = response;
if (this.selectModel.region && this.selectModel.region.regionId) {
this.selectedRegion = this.regionList.find(
c => c.regionId === this.selectModel.region?.regionId
);
}
},
error: (error) => {
console.error('Error fetching country list:', error);
}
});
}
ngOnInit(): void {
this.getJobtype();
this.getCountryList();
this.getRegionList();
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.provinceId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.shortTname?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.shortEname?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: ProvinceModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.provinceservice.deleteById(item.provinceId).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new ProvinceModel();
this.selectModel.provinceId = "";
this.selectModel.shortTname = "";
this.selectModel.shortEname = "";
this.selectModel.thName = "";
this.selectModel.engName = "";
this.selectedCountry = undefined;
this.selectedRegion = undefined
}
view(item: ProvinceModel) {
this.action = 'edit';
this.selectModel = new ProvinceModel(item);
if (this.selectModel.country && this.countryList) {
this.selectedCountry = this.countryList.find(
c => c.countryId === this.selectModel.country?.countryId
);
}
if (this.selectModel.region && this.regionList) {
this.selectedRegion = this.regionList.find(
r => r.regionId === this.selectModel.region?.regionId
)
}
}
onCountryChange(selectedCountry: CountryModel): void {
this.selectedCountry = selectedCountry;
this.selectModel.country = selectedCountry;
}
compareCountries(country1: CountryModel, country2: CountryModel): boolean {
return country1 && country2 ? country1.countryId === country2.countryId : country1 === country2;
}
onRegionChange(selectedRegion: RegionModel): void {
this.selectedRegion = selectedRegion;
this.selectModel.region = selectedRegion;
}
compareRegion(region1: RegionModel, region2: RegionModel): boolean {
return region1 && region2 ? region1.regionId === region2.regionId : region1 === region2;
}
save() {
console.log('Before Save, selectModel is:', this.selectModel);
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willSave: any) => {
if (willSave) {
this.provinceservice.post(this.selectModel).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.provinceId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.provinceId));
}
onCheckboxChange(provinceId: string) {
const isSelected = this.selectedItems.get(provinceId) || false;
this.selectedItems.set(provinceId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.provinceId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.provinceId));
}
deleteSelect() {
let companyInfo = '';
const selectedprovinceIdsToDelete: string[] = [];
this.selectedItems.forEach((isSelected, provinceId) => {
if (isSelected) {
const item = this.itemsList.find(c => c.provinceId === provinceId);
if (item) {
companyInfo += `${this.translate.instant('บริษัท')}: ${item.thName}\n`;
selectedprovinceIdsToDelete.push(item.provinceId);
}
}
});
if (selectedprovinceIdsToDelete.length === 0) {
swal("ข้อผิดพลาด", "กรุณาเลือกบริษัทที่ต้องการลบ", "warning");
return;
}
swal({
title: "คุณแน่ใจหรือไม่?",
text: companyInfo,
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
const deletePromises = selectedprovinceIdsToDelete.map(provinceId =>
this.provinceservice.deleteById(provinceId).toPromise()
.then(() => true)
.catch(error => {
console.error(`Error deleting company ${provinceId}:`, error);
return false;
})
);
Promise.all(deletePromises)
.then(results => {
const allSuccessful = results.every(success => success);
if (allSuccessful) {
swal("ลบสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
this.ngOnInit();
this.selectedItems.clear();
this.allSelected = false;
this.someSelected = false;
});
}
});
}
}
:host {
display: block;
}
.small-html {
font-size: 0.85rem; /* ลดขนาดฟอนต์ */
line-height: 1.2; /* ลดระยะบรรทัด */
max-height: 150px; /* จำกัดความสูง */
overflow-y: auto; /* ถ้าเนื้อหายาวเกิน ให้เลื่อนดูได้ */
display: block;
}
<app-page-header [title]="'จัดการบริษัท'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการบริษัท'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect(1)"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">บริษัท</th>
<th scope="col" class="text-start">อีเมล</th>
<th scope="col" class="text-start">{{"Status" | translate}}</th>
<!-- <th scope="col" class="text-start">{{"Update Date" | translate}}</th> -->
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for (item of filterList; track item.companyId) {
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox">
<input class="form-check-input" type="checkbox" [checked]="selectedItems.get(item.companyId) || false"
(change)="onCheckboxChange(item.companyId)" aria-label="...">
</td>
<td>
<div class="flex items-center">
<span class="avatar avatar-sm p-1 me-1 bg-light !rounded-full">
<img [src]="item.getPicture()" alt="" id="profile-img">
</span>
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary">
<a routerLink="/company/home/{{item.companyId}}" routerLinkActive="active">
{{item.thName}}
</a>
</p>
</div>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{item.email}}
<!-- {{item.thFirstnameContact}} {{item.thLastnameContact}} -->
</span>
</div>
</td>
<td>
<span class="badge bg-{{ item.status == 1 ? 'primary' : 'warning'}} text-white">
{{item.getStatus()}}
</span>
</td>
<!-- <td>
<span class="badge bg-info/10 text-primary">
<i class="bi bi-clock me-1"></i>
{{item.updatedAt | date : 'medium'}}
</span>
</td> -->
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Company' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="selectModel.getPicture()" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input (click)="triggerFileInput()" ng2FileSelect [uploader]="uploaderProfile" type="file"
name="photo" class="absolute w-full h-full opacity-[0]" id="profile-change"
[disabled]="action === 'edit'">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="action == 'edit'">
<label for="companyId" class="form-label">{{'รหัสบริษัท' | translate}}</label>
<input type="text" class="form-control !bg-input-readonly" id="companyId" placeholder=""
[(ngModel)]="selectModel.companyId" [disabled]="action === 'edit'">
<!-- <div class="text-danger" *ngIf="!selectModel.companyId && action === 'add'">
{{'Please fill in information' | translate}}
</div> -->
</div>
<div class="xl:col-span-12 col-span-12">
<label for="thName" class="form-label">{{'ชื่อบริษัท ไทย' | translate}}</label>
<input type="text" class="form-control" id="thName" placeholder="" [(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="thName" class="form-label">{{'ชื่อบริษัท อังกฤษ' | translate}}</label>
<input type="text" class="form-control" id="thName" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="email" class="form-label">{{'Email' | translate}}</label>
<input type="email" class="form-control" id="emailAddress" placeholder="Email Addresss"
[(ngModel)]="selectModel.email" (input)="filterEngInput($event)">
<div class="text-danger" *ngIf="!selectModel.email">
{{ 'Please fill in information' | translate }}
</div>
<div class="text-danger" *ngIf="selectModel.email && (!selectModel.email.includes('@'))">
{{ 'Invalid email format @' | translate }}
</div>
<div class="text-danger"
*ngIf="selectModel.email && selectModel.email.includes('@') && !selectModel.email.split('@')[1]?.includes('.')">
{{ 'Invalid email format .' | translate }}
</div>
</div>
<!-- <div class="xl:col-span-6 col-span-12" *ngIf="action !== 'edit'">
<label for="password" class="form-label">{{'Password' | translate}}</label>
<input type="password" class="form-control" id="password" placeholder="" [(ngModel)]="password">
<div class="text-danger" *ngIf="!password">
{{ 'Please fill in information' | translate }}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="action !== 'edit'">
<label for="deal-title" class="form-label">{{'Confirm Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder="" [(ngModel)]="confirmPassword">
<div class="text-danger" *ngIf="!confirmPassword">
{{'Please fill in information' | translate}}
</div>
<div class="text-danger" *ngIf="confirmPassword && (confirmPassword != password)">
{{'Password Not Match' | translate}}
</div>
</div> -->
<!-- <div class="xl:col-span-12 col-span-12">
<label for="companyDetail" class="form-label">{{'ข้อมูลบริษัท' | translate}}</label>
<textarea class="form-control" id="companyDetail" placeholder="" [(ngModel)]="selectModel.companyDetail">
</textarea>
<app-rendered-html class="small-html" [htmlContent]="selectModel.companyDetail" *ngIf="action === 'edit'">
</app-rendered-html>
<div class="text-danger" *ngIf="!selectModel.companyDetail">
{{'Please fill in information' | translate}}
</div>
</div> -->
<!-- <div class="xl:col-span-12 col-span-12">
<label for="locationDetail" class="form-label">{{'ที่อยู่' | translate}}</label>
<textarea class="form-control" id="locationDetail" placeholder="" [(ngModel)]="selectModel.locationDetail">
</textarea>
<app-rendered-html class="small-html" [htmlContent]="selectModel.locationDetail" *ngIf="action === 'edit'">
</app-rendered-html>
</div> -->
<!-- <div class="xl:col-span-6 col-span-12">
<label for="thFirstnameContact" class="form-label">{{'ชื่อเจ้าของ' | translate}}</label>
<input type="text" class="form-control" id="thFirstnameContact" placeholder=""
[(ngModel)]="selectModel.thFirstnameContact">
</div> -->
<!-- <div class="xl:col-span-6 col-span-12">
<label for="thLastnameContact" class="form-label">{{'นามสกุลเจ้าของ' | translate}}</label>
<input type="text" class="form-control" id="thLastnameContact" placeholder=""
[(ngModel)]="selectModel.thLastnameContact">
</div> -->
<!-- <div class="xl:col-span-12 col-span-12">
<label for="phoneContact" class="form-label">{{'เบอร์ติดต่อ' | translate}}</label>
<input type="text" class="form-control" id="phoneContact" placeholder=""
[(ngModel)]="selectModel.phoneContact">
</div> -->
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="statusSelect" id="statusSelect" placeholder="" [(ngModel)]="selectModel.status">
<ng-option [value]="0">{{'Pending' | translate}}</ng-option>
<ng-option [value]="1">{{'Public' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button *ngIf="action === 'add'" type="button" (click)="save()"
class="ti-btn bg-primary text-white !font-medium" [class.ti-btn-disabled]="!selectModel.thName||
!selectModel.engName ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.'))"
[disabled]="!selectModel.thName||
!selectModel.engName ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.'))">
<!-- !password || !confirmPassword || (confirmPassword !== password)" -->
{{'Save' | translate}}</button>
<button *ngIf="action === 'edit'" type="button" (click)="save()"
class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!selectModel.thName||
!selectModel.engName ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.'))"
[disabled]="!selectModel.thName||
!selectModel.engName ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.'))">
{{'Save' | translate}}</button>
</div>
</div>
</div>
</div>
<!-- <div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect(1)"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
<div>ไม่เอา
<input class="form-control form-control" type="text" placeholder="กรองตามบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
<a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">บริษัท</th>
<th scope="col" class="text-start">รหัสย่อบริษัท</th>
<th scope="col" class="text-start">ข้อมูลบริษัท</th>
<th scope="col" class="text-start">{{"Status" | translate}}</th>
<th scope="col" class="text-start">{{"Update Date" | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.companyId)" (change)="onCheckboxChange(item.companyId)"
aria-label="..." value="">
</td>
<td>
<div class="flex items-center">
<span class="avatar avatar-sm p-1 me-1 bg-light !rounded-full">
<img [src]="item.getPicture()" alt="" id="profile-img">
</span>
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a
routerLink="/company/home/{{item.companyId}}" routerLinkActive="active">
{{item.companyName}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.companyId}}</p>
</div>
</div>
</td>
<td>ไม่เอา
<div class="flex">
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a routerLink="/company/home/{{item.companyId}}" routerLinkActive="active">
{{item.companyName}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.companyId}}</p>
</div>
</div>
</td>
<td> {{item.companyCode}}</td>
<td>
<div>
<span class="block mb-1"><i
class="ri-home-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.companyInfo}}</span>
</div>
</td>
<td> <span
class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span>
</td>
<td><span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.updatedAt | date
: 'medium'}}</span></td>
<td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? '[disabled]="action === 'edit'"' : ''}}"><a
class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Company' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="selectModel.getPicture()" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input ng2FileSelect [uploader]="uploaderProfile" type="file" name="photo"
class="absolute w-full h-full opacity-[0]" id="profile-change">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'ชื่อบริษัท' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.companyName">
<div class="text-danger" *ngIf="!selectModel.companyName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'รหัสบริษัท' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.companyCode">
<div class="text-danger" *ngIf="!selectModel.companyCode">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'ข้อมูลบริษัท' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.companyInfo">
<div class="text-danger" *ngIf="!selectModel.companyInfo">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'ที่อยู่' | translate}}</label>
<textarea type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.address"></textarea>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'เจ้าของ' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.ownerName">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'เบอร๋ติดต่อ' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.contact">
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="choices-multiple-remove-button2" id="choices-multiple-remove-button2" placeholder=""
[(ngModel)]="selectModel.status">
<ng-option [value]="0">{{'Pending' | translate}}</ng-option>
<ng-option [value]="1" selected>{{'Public' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div> -->
<!-- End:: Create Contact -->
\ No newline at end of file
import { Component, ElementRef, ViewChild } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../../../shared/shared.module';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import swal from 'sweetalert';
import { MatPaginator } from '@angular/material/paginator';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common';
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from '../../../../environments/environment';
import { TokenService } from '../../../shared/services/token.service';
import { CompanyModelS } from '../../models/companys.mode';
import { CompanyServiceS } from '../../services/companys.service';
import { AuthModel } from '../../models/auth.model';
import { RoleModel } from '../../models/role.model';
@Component({
selector: 'app-company-manage',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
RouterModule,
FileUploadModule
],
templateUrl: './company-manage.component.html',
styleUrl: './company-manage.component.css',
})
export class CompanyManageComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild('profileChangeInput') profileChangeInputRef!: ElementRef;
action = "new";
allSelected = false;
someSelected = false;
itemsList: CompanyModelS[] = [];
filterList: CompanyModelS[] = [];
selectModel: CompanyModelS = new CompanyModelS();
selectedItems = new Map<string, boolean>();
existingEmails: CompanyModelS[] = []
// empList: CompanyModelS[] = [];
// descName = 'engName';
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
password: string = '';
confirmPassword = ""
isEmailDuplicate = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false;
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems();
}
}
_searchTerm = "";
constructor(private comService: CompanyServiceS, public translate: TranslateService, private tokenService: TokenService) {
this.uploadConfig();
}
uploadConfig() {
this.uploaderProfile = new FileUploader({
url: environment.baseUrl + "/files/upload-image",
isHTML5: true,
authToken: this.tokenService.getToken()!,
});
this.uploaderProfile.onAfterAddingFile = (fileItem: FileItem) => {
fileItem.withCredentials = false;
this.uploadErrorMsg = "";
while (this.uploaderProfile!.queue.length > 1) {
this.uploaderProfile!.queue[0].remove();
}
if (fileItem.file.size > 5000000) {
this.uploadErrorMsg = "maximum file size 5mb.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
if (fileItem.file.type!.indexOf("image") === -1) {
this.uploadErrorMsg = "please upload image only.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
fileItem.upload();
};
this.uploaderProfile.onCompleteItem = (
item: FileItem,
response: string,
status: number,
headers: ParsedResponseHeaders
) => {
if (item.isSuccess) {
const res = JSON.parse(response);
console.log("res", res);
this.selectModel.photoGraph = res.resultObject;
swal(res.message, "บันทึกสำเร็จ", "success");
} else {
this.uploadErrorMsg = "cannot upload file.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
}
};
}
getCompany() {
this.comService.getList().subscribe({
next: (response: CompanyModelS[]) => {
this.itemsList = response.map((x: any) => new CompanyModelS(x, this.translate));
console.log('ข้อมูลบริษัท (itemsList)', this.itemsList);
this.updatePagedItems();
},
error: (error) => {
console.error('error cant get company', error);
swal("ข้อผิดพลาด", "ไม่สามารถดึงข้อมูลบริษัทได้", "error");
}
});
}
ngOnInit(): void {
this.getCompany();
}
onEmailChange(email: string) {
const lowerEmail = email.trim().toLowerCase();
this.isEmailDuplicate = this.existingEmails.some(
user => user.email && user.email.toLowerCase() === lowerEmail
);
}
filter(v: string) {
return this.itemsList?.filter(
(x) =>
x.companyId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.companyDetail?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.locationDetail?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thFirstnameContact?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: CompanyModelS) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณจะไม่สามารถกู้คืนข้อมูลนี้ได้!",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ใช่, ลบเลย!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.comService.put(item).subscribe(result => {
swal("ลบสำเร็จ!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
}, error => {
console.error("เกิดข้อผิดพลาดในการลบ:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถลบข้อมูลได้", "error");
});
}
});
}
new() {
this.action = 'add';
this.selectModel = new CompanyModelS();
this.selectModel.status = 1;
this.selectModel.locationDetail = "";
this.selectModel.latitude = "";
this.selectModel.longitude = "";
this.selectModel.photoGraph = "";
this.selectModel.thName = "";
this.selectModel.companyId = "";
this.selectModel.companyDetail = "";
this.selectModel.thFirstnameContact = "";
this.selectModel.updatedAt = new Date().toISOString();
}
view(item: CompanyModelS) {
this.action = 'edit';
this.selectModel = new CompanyModelS(item);
console.log(this.selectModel);
}
save() {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willSave: any) => {
if (willSave) {
if (this.action === 'add') {
this.comService.saveOrUpdateCompany(this.selectModel).subscribe(result => {
console.log(result);
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
} else if (this.action === 'edit') {
this.comService.saveOrUpdateCompany(this.selectModel).subscribe({
next: result => {
swal("Update Success!!", "บันทึกข้อมูลบริษัท", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
},
error: err => {
swal("Error", "ไม่สามารถอัปเดตได้", "error");
}
});
}
}
});
}
// save() {
// swal({
// title: "คุณแน่ใจหรือไม่?",
// text: "คุณต้องการบันทึกหรือไม่",
// icon: "warning",
// dangerMode: false,
// buttons: ["ยกเลิก", "ยืนยัน"],
// })
// .then((willSave: any) => {
// if (willSave) {
// if (this.action === 'add') {
// const body = new AuthModel();
// body.username = this.selectModel.email;
// body.password = this.password;
// body.role = new RoleModel({ roleId: 'employer' });
// const rawCompany = { ...body.company };
// rawCompany.thName = rawCompany.thName || this.selectModel.thName || "";
// rawCompany.engName = rawCompany.engName || this.selectModel.engName || "";
// rawCompany.email = rawCompany.email || this.selectModel.email || "";
// rawCompany.status = rawCompany.status ?? 1;
// body.company = new CompanyModelS(rawCompany);
// console.log(body);
// this.comService.register(body).subscribe({
// next: res => {
// if (this.selectModel.status === 1) {
// swal("Save Success!!", "บันทึกข้อมูลบริษัท", "success");
// this.ngOnInit();
// this.childModal?.nativeElement.click();
// } else {
// swal("Save Failed", res?.message || "ไม่สามารถลงทะเบียนได้", "warning");
// }
// },
// error: err => {
// console.error('Error response:', err);
// const errorMessage = err?.error?.message || err?.message || 'ไม่ทราบสาเหตุ';
// if (errorMessage.includes('email')) {
// swal("Save Failed", "อีเมลซ้ำหรือไม่ถูกต้อง", "warning");
// } else {
// swal("Error", errorMessage, "error");
// }
// }
// });
// } else if (this.action === 'edit') {
// this.comService.saveOrUpdateCompany(this.selectModel).subscribe({
// next: result => {
// swal("Update Success!!", "บันทึกข้อมูลบริษัท", "success");
// this.ngOnInit();
// this.childModal?.nativeElement.click();
// },
// error: err => {
// swal("Error", "ไม่สามารถอัปเดตได้", "error");
// }
// });
// }
// }
// });
// }
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.companyId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.companyId));
}
onCheckboxChange(companyId: string) {
const isSelected = this.selectedItems.get(companyId) || false;
this.selectedItems.set(companyId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.companyId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.companyId));
}
deleteSelect() {
let employerInfo = '';
this.selectedItems.forEach((isSelected, companyId) => {
if (isSelected) {
const com = this.itemsList.find(com => com.companyId === companyId);
if (com) {
employerInfo += `${this.translate.instant('Fullname')}: ${com.getName()}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employerInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, companyId) => {
if (isSelected) {
const com = this.itemsList.find(com => com.companyId === companyId);
if (com) {
this.comService.put(com).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
adjustSelect(status: number) {
let title = "คุณแน่ใจหรือไม่?";
let companyInfo = '';
const selectedCompanies: CompanyModelS[] = [];
this.selectedItems.forEach((isSelected, companyId) => {
if (isSelected) {
const company = this.itemsList.find(c => c.companyId === companyId);
if (company) {
companyInfo += `${this.translate.instant('ชื่อบริษัท')}: ${company.thName}\n`;
selectedCompanies.push(company);
}
}
});
if (selectedCompanies.length === 0) {
swal("ข้อผิดพลาด", "กรุณาเลือกบริษัทที่ต้องการปรับสถานะ", "warning");
return;
}
swal({
title: title,
text: companyInfo,
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
})
.then((willAdjust: any) => {
if (willAdjust) {
const updatePromises = selectedCompanies.map(company => {
company.status = status;
console.log(company);
const respone = new CompanyModelS(company);
return this.comService.saveOrUpdateCompany(respone).toPromise()
.then(() => true)
.catch(error => {
console.error(`Error updating status for company ${company.companyId}:`, error);
return false;
});
});
Promise.all(updatePromises)
.then(results => {
const allSuccessful = results.every(success => success);
if (allSuccessful) {
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการอัปเดตสถานะบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
this.ngOnInit();
this.selectedItems.clear();
this.allSelected = false;
this.someSelected = false;
});
}
});
}
triggerFileInput(): void {
if (this.profileChangeInputRef) {
this.profileChangeInputRef.nativeElement.click();
}
}
filterEngInput(event: any): void {
const input = event.target.value;
const filtered = input.replace(/[^a-zA-Z0-9 @\/.,!?()\-_:*%&$#"]/g, '');
event.target.value = filtered;
}
}
// import { Component, ElementRef, ViewChild } from '@angular/core';
// import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
// import { RouterModule } from '@angular/router';
// import { SharedModule } from '../../../shared/shared.module';
// import { TranslateModule, TranslateService } from '@ngx-translate/core';
// import { CompanyModel } from '../../models/company.model';
// import swal from 'sweetalert';
// import { CompanyService } from '../../services/company.service';
// import { MatPaginator } from '@angular/material/paginator';
// import { FormsModule } from '@angular/forms';
// import { NgSelectModule } from '@ng-select/ng-select';
// import { CommonModule } from '@angular/common';
// import { FileUploadModule } from 'ng2-file-upload';
// import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
// import { environment } from '../../../../environments/environment';
// import { TokenService } from '../../../shared/services/token.service';
// @Component({
// selector: 'app-company-manage',
// standalone: true,
// imports: [
// CommonModule,
// SharedModule,
// TranslateModule,
// NgSelectModule,
// FormsModule,
// MatPaginator,
// RouterModule,
// FileUploadModule
// ],
// templateUrl: './company-manage.component.html',
// styleUrl: './company-manage.component.css',
// })
// export class CompanyManageComponent {
// @ViewChild('closeModal') public childModal?: ElementRef;
// @ViewChild('modalDetail') public modalDetail?: ElementRef;
// action = "new";
// allSelected = false;
// someSelected = false;
// itemsList: CompanyModel[] = []
// filterList: CompanyModel[] = []
// selectModel: CompanyModel = new CompanyModel()
// selectedItems = new Map<string, boolean>();
// empList: CompanyModel[] = []
// descName = 'engName'
// pageIndex = 0;
// uploaderProfile: FileUploader | undefined;
// uploadErrorMsg: string = "";
// get searchTerm(): string {
// return this._searchTerm;
// }
// set searchTerm(val: string) {
// this.pageIndex = 0;
// this.allSelected = false
// this._searchTerm = val;
// if (val != '') {
// this.filterList = this.filter(val);
// } else {
// this.updatePagedItems()
// }
// }
// _searchTerm = "";
// constructor(private comService: CompanyService, public translate: TranslateService, private tokenService: TokenService) {
// this.uploadConfig()
// }
// uploadConfig() {
// this.uploaderProfile = new FileUploader({
// url: environment.baseUrl + "/api/upload-image",
// isHTML5: true,
// authToken: this.tokenService.getToken()!,
// });
// this.uploaderProfile.onAfterAddingFile = (fileItem: FileItem) => {
// fileItem.withCredentials = false;
// this.uploadErrorMsg = "";
// while (this.uploaderProfile!.queue.length > 1) {
// this.uploaderProfile!.queue[0].remove();
// }
// if (fileItem.file.size > 5000000) {
// this.uploadErrorMsg = "maximum file size 5mb.";
// swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
// fileItem.isCancel = true;
// return;
// }
// if (fileItem.file.type!.indexOf("image") === -1) {
// this.uploadErrorMsg = "please upload image only.";
// swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
// fileItem.isCancel = true;
// return;
// }
// fileItem.upload();
// };
// this.uploaderProfile.onCompleteItem = (
// item: FileItem,
// response: string,
// status: number,
// headers: ParsedResponseHeaders
// ) => {
// if (item.isSuccess) {
// const res = JSON.parse(response);
// console.log("res", res);
// this.selectModel.picture = res.filename
// swal(res.message, "บันทึกสำเร็จ", "success");
// } else {
// this.uploadErrorMsg = "cannot upload file.";
// swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
// }
// };
// }
// ngOnInit(): void {
// this.comService.getLists().subscribe(result => {
// this.itemsList = result
// this.updatePagedItems()
// })
// }
// filter(v: string) {
// return this.itemsList?.filter(
// (x) =>
// x.companyId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.companyName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.companyCode?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.companyInfo?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.address.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.ownerName.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
// x.getStatus().toLowerCase().indexOf(v.toLowerCase()) !== -1
// );
// }
// delete(item: CompanyModel) {
// swal({
// title: "Are you sure?",
// text: "You won't be able to revert this!",
// icon: "warning",
// dangerMode: true,
// buttons: ["Cancel", "Yes,Delete it!"],
// })
// .then((willDelete: any) => {
// if (willDelete) {
// this.comService.delete(item).subscribe(result => {
// swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// this.ngOnInit()
// })
// }
// });
// }
// new() {
// this.action = 'add'
// this.selectModel = new CompanyModel()
// this.selectModel.status = 1;
// this.selectModel.address = "";
// this.selectModel.latitude = 0.00
// this.selectModel.longitude = 0.00
// this.selectModel.picture = ""
// }
// view(item: CompanyModel) {
// this.action = 'edit'
// this.selectModel = new CompanyModel(item)
// console.log(this.selectModel)
// }
// save() {
// swal({
// title: "Are you sure?",
// text: "คุณต้องการบันทึกหรือไม่",
// icon: "warning",
// dangerMode: false,
// buttons: ["Cancel", "Confirm"],
// })
// .then((willDelete: any) => {
// if (willDelete) {
// if (this.action == 'add') {
// this.comService.save(this.selectModel).subscribe(result => {
// console.log(result)
// swal("Save Success!!", "บันทึกข้อมูลสมาชิก", "success");
// this.ngOnInit()
// this.childModal?.nativeElement.click()
// })
// } else if (this.action == 'edit') {
// this.comService.update(this.selectModel).subscribe(result => {
// console.log(result)
// swal("Update Success!!", "บันทึกข้อมูลสมาชิก", "success");
// this.ngOnInit()
// this.childModal?.nativeElement.click()
// })
// }
// }
// });
// }
// updatePagedItems() {
// const startIndex = this.pageIndex * 10;
// const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
// }
// toggleAll(event: any) {
// this.allSelected = event.target.checked;
// this.selectedItems.clear();
// this.itemsList.forEach(item => {
// this.selectedItems.set(item.companyId, this.allSelected);
// });
// this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.companyId));
// }
// onCheckboxChange(companyId: string) {
// const isSelected = this.selectedItems.get(companyId) || false;
// this.selectedItems.set(companyId, !isSelected);
// this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.companyId));
// this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.companyId));
// }
// deleteSelect() {
// let employeeInfo = '';
// this.selectedItems.forEach((isSelected, companyId) => {
// if (isSelected) {
// const item = this.itemsList.find(item => item.companyId === companyId);
// if (item) {
// employeeInfo += `${this.translate.instant('บริษัท')}: ${item.companyName}\n`;
// }
// }
// });
// swal({
// title: "Are you sure?",
// text: employeeInfo,
// icon: "warning",
// dangerMode: true,
// buttons: ["Cancel", "Yes, Delete it!"],
// })
// .then((willDelete: any) => {
// if (willDelete) {
// this.selectedItems.forEach((isSelected, companyId) => {
// if (isSelected) {
// const item = this.itemsList.find(item => item.companyId === companyId);
// if (item) {
// this.comService.delete(item).subscribe(result => {
// swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// this.ngOnInit();
// });
// }
// }
// });
// }
// });
// }
// adjustSelect(status: number) {
// let title = "Are you sure?"
// let employeeInfo = ''; // ตัวแปรสำหรับเก็บข้อมูลพนักงาน
// this.selectedItems.forEach((isSelected, memberId) => {
// if (isSelected) {
// const company = this.itemsList.find(company => company.companyId === memberId);
// if (company) {
// employeeInfo += `${this.translate.instant('Fullname')}: ${company.companyName}\n`;
// }
// }
// });
// swal({
// title: title,
// text: employeeInfo,
// icon: "warning",
// dangerMode: false,
// buttons: ["Cancel", "Confirm"],
// })
// .then((willDelete: any) => {
// if (willDelete) {
// this.selectedItems.forEach((isSelected, companyId) => {
// if (isSelected) {
// const company = this.itemsList.find(company => company.companyId === companyId);
// if (company) {
// company.status = status
// this.comService.update(company).subscribe(result => {
// swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// this.ngOnInit();
// });
// }
// }
// });
// }
// });
// }
// }
<app-page-header [title]="'Department'" [activeTitle]="'จัดการบริษัท'" [title1]="'Department'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="{{ 'Search' | translate}}"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'ชื่อแผนก' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.departmentId)" (change)="onCheckboxChange(item.departmentId)"
aria-label="..." value="">
</td>
<td><span class="font-semibold text-primary">{{item.departmentId}}</span></td>
<td> {{item.thName}}</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Department' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-6 col-span-12">
<label for="contact-lead-score" class="form-label">{{'Name (TH)' | translate}}</label>
<input type="text" class="form-control" id="contact-lead-score" placeholder=""
[(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="contact-mail" class="form-label">{{'Name (EN)' | translate}}</label>
<input type="text" class="form-control" id="contact-mail" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" [disabled]="!selectModel.thName || !selectModel.engName"
class="ti-btn bg-primary text-white !font-medium {{!selectModel.thName || !selectModel.engName ? 'ti-btn-disabled' : ''}}"
(click)="save()">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { SharedModule } from "../../../../shared/shared.module";
import { DepartmentService } from "../../../services/department.service";
import { DepartmentModel } from "../../../models/department.model";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { ActivatedRoute } from "@angular/router";
import { TokenService } from "../../../../shared/services/token.service";
@Component({
selector: 'app-department',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator
],
templateUrl: './department.component.html',
styleUrl: './department.component.css'
})
export class DepartmentComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
allSelected = false;
someSelected = false;
companyId = ""
itemsList: DepartmentModel[] = []
filterList: DepartmentModel[] = [];
selectModel: DepartmentModel = new DepartmentModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
isEdit = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private departmentService: DepartmentService, private tokenService: TokenService, public translate: TranslateService) {
this.companyId = this.tokenService.getSelectCompany().companyId;;
this.getDepartment()
}
getDepartment() {
this.departmentService.getLists(this.companyId).subscribe(result => {
this.itemsList = result
this.updatePagedItems()
})
}
filter(v: string) {
this.pageIndex = 0;
return this.itemsList?.filter(
(x) =>
x.departmentId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: DepartmentModel) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
timer: 1000,
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.departmentService.delete(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getDepartment()
})
}
});
}
new() {
this.isEdit = false
this.selectModel = new DepartmentModel()
}
view(item: DepartmentModel) {
this.isEdit = true;
this.selectModel = new DepartmentModel(item)
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectModel.companyId = this.companyId
if (!this.isEdit) {
this.departmentService.save(this.selectModel).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getDepartment()
this.childModal?.nativeElement.click()
})
} else {
this.departmentService.update(this.selectModel).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getDepartment()
this.childModal?.nativeElement.click()
})
}
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.departmentId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.departmentId));
}
onCheckboxChange(departmentId: string) {
const isSelected = this.selectedItems.get(departmentId) || false;
this.selectedItems.set(departmentId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.departmentId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.departmentId));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, departmentId) => {
if (isSelected) {
const item = this.itemsList.find(item => item.departmentId === departmentId);
if (item) {
employeeInfo += `${this.translate.instant('ชื่อตำแหน่ง')}: ${item.getName()}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, departmentId) => {
if (isSelected) {
const item = this.itemsList.find(item => item.departmentId === departmentId);
if (item) {
this.departmentService.delete(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getDepartment();
});
}
}
});
}
});
}
}
<app-page-header [title]="'Position'" [activeTitle]="'จัดการบริษัท'" [title1]="'Position'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="{{ 'Search' | translate}}"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'ชื่อตำแหน่ง' | translate}}</th>
<!-- <th scope="col" class="text-start">{{ 'Name (EN)' | translate}}</th> -->
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.positionId)" (change)="onCheckboxChange(item.positionId)"
aria-label="..." value="">
</td>
<td><span class="font-semibold text-primary">{{item.positionId}}</span></td>
<td> {{item.thName}}</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">{{ 'Create' |
translate }} {{ 'Position' | translate }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<!-- <div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'ID' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.positionId">
<div class="text-danger" *ngIf="!selectModel.positionId">
{{'Please fill in information' | translate}}
</div>
</div> -->
<div class="xl:col-span-6 col-span-12">
<label for="contact-lead-score" class="form-label">{{'Name (TH)' | translate}}</label>
<input type="text" class="form-control" id="contact-lead-score" placeholder=""
[(ngModel)]="selectModel.thName">
<div class="text-danger" *ngIf="!selectModel.thName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="contact-mail" class="form-label">{{'Name (EN)' | translate}}</label>
<input type="text" class="form-control" id="contact-mail" placeholder="" [(ngModel)]="selectModel.engName">
<div class="text-danger" *ngIf="!selectModel.engName">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" [disabled]="!selectModel.thName || !selectModel.engName"
class="ti-btn bg-primary text-white !font-medium {{!selectModel.thName || !selectModel.engName ? 'ti-btn-disabled' : ''}}"
(click)="save()">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { SharedModule } from "../../../../shared/shared.module";
import { PositionService } from "../../../services/position.service";
import { PositionModel } from "../../../models/position.model";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { ActivatedRoute } from "@angular/router";
import { TokenService } from "../../../../shared/services/token.service";
@Component({
selector: 'app-position',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
MatPaginator
],
templateUrl: './position.component.html',
styleUrl: './position.component.css'
})
export class PositionComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
allSelected = false;
someSelected = false;
companyId = ""
itemsList: PositionModel[] = []
filterList: PositionModel[] = [];
selectModel: PositionModel = new PositionModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
isEdit = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private positionService: PositionService, private tokenService: TokenService, public translate: TranslateService) {
this.companyId = this.tokenService.getSelectCompany().companyId;;
this.getPosition()
}
ngOnInit(): void {
}
getPosition() {
this.positionService.getLists(this.companyId).subscribe(result => {
this.itemsList = result
this.updatePagedItems()
})
}
filter(v: string) {
this.pageIndex = 0;
return this.itemsList?.filter(
(x) =>
x.positionId?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.thName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.engName?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
delete(item: PositionModel) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
timer: 1000,
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.positionService.delete(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getPosition()
})
}
});
}
new() {
this.isEdit = false
this.selectModel = new PositionModel()
}
view(item: PositionModel) {
this.isEdit = true;
this.selectModel = new PositionModel(item)
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectModel.companyId = this.companyId
if (!this.isEdit) {
this.positionService.save(this.selectModel).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getPosition()
this.getPosition()
this.childModal?.nativeElement.click()
})
} else {
this.positionService.update(this.selectModel).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getPosition()
this.getPosition()
this.childModal?.nativeElement.click()
})
}
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.positionId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.positionId));
}
onCheckboxChange(positionId: string) {
const isSelected = this.selectedItems.get(positionId) || false;
this.selectedItems.set(positionId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.positionId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.positionId));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, positionId) => {
if (isSelected) {
const item = this.itemsList.find(item => item.positionId === positionId);
if (item) {
employeeInfo += `${this.translate.instant('ชื่อตำแหน่ง')}: ${item.getName()}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, positionId) => {
if (isSelected) {
const item = this.itemsList.find(item => item.positionId === positionId);
if (item) {
this.positionService.delete(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getPosition();
});
}
}
});
}
});
}
}
<app-page-header [title]="'Analytics'" [activeTitle]="'Dashboards'" [title1]="'Analytics'"></app-page-header>
<div class="grid grid-cols-12 gap-x-6">
<div class="xl:col-span-7 col-span-12">
<div class="grid grid-cols-12 gap-x-6">
<div class="xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12">
<div class="box">
<div class="box-body">
<div class="flex flex-wrap items-center justify-between">
<div>
<h6 class="font-semibold mb-3 text-[1rem]">Total Users</h6>
<span class="text-[1.5625rem] font-semibold">9,789</span>
<span class="block text-success text-[0.75rem]">+0.892 <i class="ti ti-trending-up ms-1"></i></span>
</div>
<div id="analytics-users">
<apx-chart [series]="chartOptions1.series" [chart]="chartOptions1.chart"
[xaxis]="chartOptions1.xaxis" [dataLabels]="chartOptions1.dataLabels"
[colors]="chartOptions1.colors" [fill]="chartOptions1.fill"
[markers]="chartOptions1.markers" [stroke]="chartOptions1.stroke"></apx-chart>
</div>
</div>
</div>
</div>
</div>
<div class="xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12">
<div class="box">
<div class="box-body">
<div class="flex items-center justify-between">
<div>
<h6 class="font-semibold mb-3 text-[1rem]">Live Visitors</h6>
<span class="text-[1.5625rem] font-semibold">12,240</span>
<span class="block text-danger text-[0.75rem]">+0.59<i class="ti ti-trending-down ms-1 inline-flex"></i></span>
</div>
<div>
<span class="avatar avatar-md bg-secondary text-white">
<i class="ri-user-3-line"></i>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="xl:col-span-4 lg:col-span-4 md:col-span-4 sm:col-span-6 col-span-12">
<div class="box overflow-hidden">
<div class="box-body mb-3">
<div class="flex items-center justify-between">
<div>
<h6 class="font-semibold text-primary mb-4 text-[1rem]">Bounce Rate</h6>
<span class="text-[1.5625rem] flex items-center">77.3% <span class=" text-[0.75rem] text-warning opacity-[0.7] ms-2">+0.59<i class="ti ti-arrow-big-up-line ms-1 inline-flex"></i></span></span>
</div>
</div>
</div>
<div id="analytics-bouncerate" class="mt-1 w-full">
<apx-chart [series]="chartOptions2.series" [chart]="chartOptions2.chart"
[xaxis]="chartOptions2.xaxis" [dataLabels]="chartOptions2.dataLabels"
[colors]="chartOptions2.colors" [fill]="chartOptions2.fill"
[markers]="chartOptions2.markers" [stroke]="chartOptions2.stroke"></apx-chart>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
Audience Report
</div>
<div>
<button type="button" class="ti-btn ti-btn-primary ti-btn-wave !font-medium"><i class="ri-share-forward-line me-1 align-middle inline-block"></i>Export</button>
</div>
</div>
<div class="box-body">
<div id="audienceReport">
<apx-chart [series]="chartOptions.series" [chart]="chartOptions.chart"
[yaxis]="chartOptions.yaxis" [xaxis]="chartOptions.xaxis"
[labels]="chartOptions.labels" [stroke]="chartOptions.stroke"
[plotOptions]="chartOptions.plotOptions" [markers]="chartOptions.markers"
[fill]="chartOptions.fill" [tooltip]="chartOptions.tooltip" [legend]="chartOptions.legend" [colors]="chartOptions.colors"></apx-chart>
</div>
</div>
</div>
</div>
<div class="xxl:col-span-6 xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
Top Countries Sessions vs Bounce Rate
</div>
<div class="hs-dropdown ti-dropdown">
<a href="javascript:void(0);" class="px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded="false">
View All<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Today</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">This Week</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Last Week</a></li>
</ul>
</div>
</div>
<div class="box-body">
<div id="country-sessions">
<apx-chart [series]="chartOptions3.series" [chart]="chartOptions3.chart"
[yaxis]="chartOptions3.yaxis" [xaxis]="chartOptions3.xaxis"
[labels]="chartOptions3.labels" [stroke]="chartOptions3.stroke"
[plotOptions]="chartOptions3.plotOptions" [markers]="chartOptions3.markers"
[fill]="chartOptions3.fill" [tooltip]="chartOptions3.tooltip" [legend]="chartOptions3.legend" [colors]="chartOptions3.colors"></apx-chart>
</div>
</div>
</div>
</div>
<div class="xxl:col-span-6 xl:col-span-12 col-span-12">
<div class="box overflow-hidden">
<div class="box-header justify-between">
<div class="box-title">
Traffic Sources
</div>
<div class="hs-dropdown ti-dropdown">
<a href="javascript:void(0);" class="px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded="false">
View All<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Today</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">This Week</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Last Week</a></li>
</ul>
</div>
</div>
<div class="box-body !p-0">
<div class="table-responsive">
<table class="table table-hover whitespace-nowrap min-w-full">
<thead>
<tr>
<th scope="col" class="text-start">Browser</th>
<th scope="col" class="text-start">Sessions</th>
<th scope="col" class="text-start">Traffic</th>
</tr>
</thead>
<tbody>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td>
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-google-fill text-[1.125rem] text-primary"></i>
</span>
<div class="font-semibold">Google</div>
</div>
</td>
<td>
<span><i class="ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"></i>23,379</span>
</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-[78%]" aria-valuenow="78" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td>
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-safari-line text-[1.125rem] text-secondary"></i>
</span>
<div class="font-semibold">Safari</div>
</div>
</td>
<td>
<span><i class="ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"></i>78,973</span>
</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-[32%]" aria-valuenow="32" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td>
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-opera-fill text-[1.125rem] text-success"></i>
</span>
<div class="font-semibold">Opera</div>
</div>
</td>
<td>
<span><i class="ri-arrow-down-s-fill me-1 text-danger align-middle text-[1.125rem]"></i>12,457</span>
</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-[21%]" aria-valuenow="21" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td>
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-edge-fill text-[1.125rem] text-info"></i>
</span>
<div class="font-semibold">Edge</div>
</div>
</td>
<td>
<span><i class="ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"></i>8,570</span>
</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-1/4" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td>
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-firefox-fill text-[1.125rem] text-warning"></i>
</span>
<div class="font-semibold">Firefox</div>
</div>
</td>
<td>
<span><i class="ri-arrow-down-s-fill me-1 text-danger align-middle text-[1.125rem]"></i>6,135</span>
</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-[35%]" aria-valuenow="35" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
<tr class="border-t border-inherit border-solid hover:bg-gray-100 dark:hover:bg-light dark:border-defaultborder/10">
<td class="border-bottom-0">
<div class="flex items-center">
<span class="avatar avatar-rounded avatar-sm p-2 bg-light me-2">
<i class="ri-ubuntu-fill text-[1.125rem] text-danger"></i>
</span>
<div class="font-semibold">Ubuntu</div>
</div>
</td>
<td class="border-bottom-0">
<span><i class="ri-arrow-up-s-fill me-1 text-success align-middle text-[1.125rem]"></i>4,789</span>
</td>
<td class="border-bottom-0">
<div class="progress progress-xs">
<div class="progress-bar bg-primary w-[12%]" aria-valuenow="12" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="xl:col-span-5 col-span-12">
<div class="grid grid-cols-12 gap-x-6">
<div class="xxl:col-span-5 cxl:ol-span-12 col-span-12">
<div class="box custom-card upgrade-card text-white">
<div class="box-body text-white">
<span class="avatar avatar-xxl !border-0">
<img src="./assets/images/media/media-84.png" alt="">
</span>
<div class="upgrade-card-content">
<span class="opacity-[0.7] font-normal mb-1 !text-white">Plan is expiring !</span>
<span class="text-[0.9375rem] font-semibold block mb-[3rem] upgrade-text !text-white">Upgrade to premium</span>
<button type="button" class="ti-btn !py-1 !px-2 bg-light text-defaulttextcolor !text-[0.75rem] font-medium ti-btn-wave">Upgrade Now</button>
</div>
</div>
</div>
<div class="box">
<div class="box-body !p-1">
<div class="flex items-center flex-wrap">
<div id="analytics-followers">
<apx-chart [series]="optionsCircle2.series" [chart]="optionsCircle2.chart"
[xaxis]="optionsCircle2.xaxis" [colors]="optionsCircle2.colors"
[labels]="optionsCircle2.labels" [legend]="optionsCircle2.legend"
[stroke]="optionsCircle2.stroke" [tooltip]="optionsCircle2.tooltip"
[plotOptions]="optionsCircle2.plotOptions"
[dataLabels]="optionsCircle2.dataLabels"></apx-chart>
</div>
<div class="ms-1">
<p class="mb-1 text-[#8c9097] dark:text-white/50">Impressions</p>
<h5 class="font-semibold mb-0 text-[1.25rem]">9,903</h5>
</div>
</div>
</div>
</div>
<div class="box">
<div class="box-body !p-1">
<div class="flex items-center flex-wrap">
<div id="analytics-views">
<apx-chart [series]="optionsCircle3.series" [chart]="optionsCircle3.chart"
[xaxis]="optionsCircle3.xaxis" [colors]="optionsCircle3.colors"
[labels]="optionsCircle3.labels" [legend]="optionsCircle3.legend"
[stroke]="optionsCircle3.stroke" [tooltip]="optionsCircle3.tooltip"
[plotOptions]="optionsCircle3.plotOptions"
[dataLabels]="optionsCircle3.dataLabels"></apx-chart>
</div>
<div class="ms-1">
<p class="mb-1 text-[#8c9097] dark:text-white/50">Clicks</p>
<h5 class="font-semibold mb-0 text-[1.25rem]">16,789</h5>
</div>
</div>
</div>
</div>
</div>
<div class="xxl:col-span-7 xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
Sessions By Device
</div>
<div>
<button type="button" class="ti-btn ti-btn-primary 1 !text-[0.85rem] !m-0 !font-medium">View All</button>
</div>
</div>
<div class="box-body !my-2 !py-6 !px-2">
<div id="sessions">
<apx-chart [series]="optionsCircle1.series" [chart]="optionsCircle1.chart"
[xaxis]="optionsCircle1.xaxis"
[labels]="optionsCircle1.labels" [legend]="optionsCircle1.legend"
[stroke]="optionsCircle1.stroke" [tooltip]="optionsCircle1.tooltip"
[plotOptions]="optionsCircle1.plotOptions"
[dataLabels]="optionsCircle1.dataLabels"[colors]="optionsCircle1.colors"></apx-chart>
</div>
</div>
<div class="box-footer !p-0">
<div class="grid grid-cols-12 justify-center">
<div class="col-span-3 pe-0 text-center">
<div class="sm:p-4 p-2 ">
<span class="text-[#8c9097] dark:text-white/50 text-[0.6875rem]">Mobile</span>
<span class="block text-[1rem] font-semibold">68.3%</span>
</div>
</div>
<div class="col-span-3 px-0 text-center">
<div class="sm:p-4 p-2">
<span class="text-[#8c9097] dark:text-white/50 text-[0.6875rem]">Tablet</span>
<span class="block text-[1rem] font-semibold">17.68%</span>
</div>
</div>
<div class="col-span-3 px-0 text-center">
<div class="sm:p-4 p-2 ">
<span class="text-[#8c9097] dark:text-white/50 text-[0.6875rem]">Desktop</span>
<span class="block text-[1rem] font-semibold">10.5%</span>
</div>
</div>
<div class="col-span-3 px-0 text-center">
<div class="sm:p-4 p-2">
<span class="text-[#8c9097] dark:text-white/50 text-[0.6875rem]">Others</span>
<span class="block text-[1rem] font-semibold">5.16%</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">Sessions Duration By New Users</div>
<div class="hs-dropdown ti-dropdown">
<a href="javascript:void(0);" class="px-2 font-normal text-[0.75rem] text-[#8c9097] dark:text-white/50"
aria-expanded="false">
View All<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Today</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">This Week</a></li>
<li><a class="ti-dropdown-item !py-2 !px-[0.9375rem] !text-[0.8125rem] !font-medium block"
href="javascript:void(0);">Last Week</a></li>
</ul>
</div>
</div>
<div class="box-body">
<div id="session-users">
<apx-chart [series]="chartOptions4.series" [chart]="chartOptions4.chart"
[yaxis]="chartOptions4.yaxis" [xaxis]="chartOptions4.xaxis"
[labels]="chartOptions4.labels" [stroke]="chartOptions4.stroke"
[plotOptions]="chartOptions4.plotOptions" [markers]="chartOptions4.markers"
[fill]="chartOptions4.fill" [tooltip]="chartOptions4.tooltip" [colors]="chartOptions4.colors" [legend]="chartOptions4.legend"></apx-chart>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { HomeCommonComponent } from './home-common.component';
describe('HomeCommonComponent', () => {
let component: HomeCommonComponent;
let fixture: ComponentFixture<HomeCommonComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeCommonComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeCommonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, ElementRef, Renderer2 } from '@angular/core';
import { RouterModule } from '@angular/router';
import ApexCharts from 'apexcharts'
import { SharedModule } from '../../../shared/shared.module';
import { NgApexchartsModule } from 'ng-apexcharts';
@Component({
selector: 'app-home-common',
imports: [RouterModule,SharedModule,NgApexchartsModule],
standalone: true,
templateUrl: './home-common.component.html',
styleUrls: ['./home-common.component.css']
})
export class HomeCommonComponent {
chartOptions1:any;
chartOptions2:any;
chartOptions3:any
chartOptions:any;
optionsCircle1:any;
chartOptions4:any;
optionsCircle2:any;
optionsCircle3:any
constructor(private el: ElementRef, private renderer: Renderer2,private cdr: ChangeDetectorRef){
this.chartOptions1={
chart: {
type: 'line',
height: 40,
width: 120,
sparkline: {
enabled: true
},
dropShadow: {
enabled: true,
top: 0,
left: 0,
blur: 3,
color: '#000',
opacity: 0.1
},
},
grid: {
show: false,
xaxis: {
lines: {
show: false
}
},
yaxis: {
lines: {
show: false
}
},
},
stroke: {
show: true,
curve: 'straight',
lineCap: 'butt',
width: 1.5,
dashArray: 0,
},
fill: {
gradient: {
enabled: false
}
},
series: [{
name: 'Value',
data: [0, 21, 54, 38, 56, 24, 65]
}],
yaxis: {
min: 0,
show: false
},
xaxis: {
show: false,
axisTicks: {
show: false,
axisBorder: {
show: false
},
},
axisBorder: {
show: false
}
},
colors: ['#23b7e5'],
}
this.chartOptions2={
chart: {
type: 'line',
height: 45,
sparkline: {
enabled: true
},
dropShadow: {
enabled: true,
top: 0,
left: 0,
blur: 1,
color: '#fff',
opacity: 0.05
}
},
stroke: {
show: true,
curve: 'smooth',
lineCap: 'butt',
width: 2,
dashArray: 0,
},
fill: {
gradient: {
enabled: false
}
},
series: [{
name: 'Value',
data: [54, 38, 56, 35, 65, 43, 53, 45, 62, 80, 35, 48]
}],
yaxis: {
min: 0,
show: false,
axisBorder: {
show: false
},
},
xaxis: {
axisBorder: {
show: false
},
},
colors: ["rgba(132, 90, 223, 0.1)"],
tooltip: {
enabled: false,
}
}
this.optionsCircle1 = {
series: [1754, 1234, 878, 270],
labels: ["Mobile", "Tablet", "Desktop", "Others"],
chart: {
height: 250,
type: 'donut',
},
dataLabels: {
enabled: false,
},
legend: {
show: false,
},
stroke: {
show: true,
curve: 'smooth',
lineCap: 'round',
colors: ["#fff"],
width: 0,
dashArray: 0,
},
plotOptions: {
pie: {
expandOnClick: false,
donut: {
size: '80%',
background: 'transparent',
labels: {
show: true,
name: {
show: true,
fontSize: '20px',
color: '#495057',
offsetY: -4
},
value: {
show: true,
fontSize: '18px',
offsetY: 8,
formatter: function (val: string) {
return val + "%";
}
},
total: {
show: true,
showAlways: true,
label: 'Total',
fontSize: '22px',
fontWeight: 600,
color: '#495057',
}
}
},
},
},
colors: ["rgba(132, 90, 223, 1)", "rgba(35, 183, 229, 1)", "rgba(38, 191, 148, 1)", "rgba(245, 184, 73, 1)",],
};
this.chartOptions = {
series: [
{
name: 'Views',
type: 'column',
data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 45, 35],
},
{
name: 'Followers',
type: 'line',
data: [44, 55, 41, 67, 22, 43, 21, 41, 56, 27, 43, 27],
},
],
chart: {
toolbar: {
show: false,
},
type: 'line',
height: 250,
},
grid: {
borderColor: '#f1f1f1',
strokeDashArray: 3,
},
labels: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
dataLabels: {
enabled: false,
},
stroke: {
width: [1, 1.1],
curve: ['straight', 'smooth'],
},
legend: {
show: true,
position: 'top',
},
xaxis: {
axisBorder: {
color: '#e9e9e9',
},
},
plotOptions: {
bar: {
columnWidth: '20%',
borderRadius: 2,
},
},
colors: ["rgba(132, 90, 223, 1)", '#23b7e5'],
};
this.chartOptions3 = {
series: [
{
name: 'Session',
data: [24, 23, 20, 25, 27, 26, 24, 23, 23, 25, 23, 23],
type: 'line',
},
{
name: 'Bounce Rate',
data: [20, 23, 26, 22, 20, 26, 28, 26, 22, 27, 25, 26],
type: 'bar',
},
],
chart: {
height: 328,
zoom: {
enabled: false
},
},
dataLabels: {
enabled: false,
},
grid: {
borderColor: '#f1f1f1',
strokeDashArray: 3
},
legend: {
show: true,
position: 'top',
},
plotOptions: {
bar: {
borderRadius: 5,
columnWidth: "40%",
dataLabels: {
position: 'top', // top, center, bottom
},
}
},
colors: ["rgb(132, 90, 223)", "#ededed"],
stroke: {
curve: ['smooth', 'stepline'],
width: [2, 0],
},
xaxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
axisBorder: {
color: '#e9e9e9',
},
}
};
this.chartOptions4 = {
series: [
{
name: 'New Users',
data: [32, 15, 63, 51, 36, 62, 99, 42, 78, 76, 32, 120],
},
{
name: 'Sessions',
data: [56, 58, 38, 50, 64, 45, 55, 32, 15, 63, 51, 136],
},
{
name: 'Avg Session Duration',
data: [48, 29, 50, 69, 20, 59, 52, 12, 48, 28, 17, 98],
},
],
chart: {
height: 425,
type: 'line',
toolbar: {
show: false,
},
background: 'none',
fill: '#fff',
},
grid: {
borderColor: '#f2f6f7',
},
colors: ['rgb(132, 90, 223)', '#23b7e5', '#f5b849'],
background: 'transparent',
dataLabels: {
enabled: false,
},
stroke: {
curve: 'straight',
width: 3,
},
legend: {
show: true,
position: 'top',
},
xaxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
show: false,
axisBorder: {
show: false,
color: 'rgba(119, 119, 142, 0.05)',
offsetX: 0,
offsetY: 0,
},
axisTicks: {
show: false,
borderType: 'solid',
color: 'rgba(119, 119, 142, 0.05)',
width: 6,
offsetX: 0,
offsetY: 0,
},
labels: {
rotate: -90,
},
},
yaxis: {
show: false,
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm',
},
},
};
this.optionsCircle2={
chart: {
height: 120,
width: 100,
type: "radialBar",
},
series: [48],
colors: ["#23b7e5"],
plotOptions: {
radialBar: {
hollow: {
margin: 0,
size: "50%",
background: "#fff"
},
dataLabels: {
name: {
offsetY: -10,
color: "#4b9bfa",
fontSize: "10px",
show: false
},
value: {
offsetY: 5,
color: "#4b9bfa",
fontSize: "12px",
show: true,
fontWeight: 800
}
}
}
},
stroke: {
lineCap: "round"
},
labels: ["Followers"]
}
this.optionsCircle3={
chart: {
height: 120,
width: 100,
type: "radialBar",
},
series: [65],
colors: ["#ffc107"],
plotOptions: {
radialBar: {
hollow: {
margin: 0,
size: "50%",
background: "#fff"
},
dataLabels: {
name: {
offsetY: -10,
color: "#4b9bfa",
fontSize: "10px",
show: false
},
value: {
offsetY: 5,
color: "#4b9bfa",
fontSize: "12px",
show: true,
fontWeight: 800
},
}
}
},
stroke: {
lineCap: "round"
},
labels: ["Views"]
}
}
// ngAfterViewInit(): void {
// this.setChartWidth();
// this.cdr.detectChanges();
// }
// private setChartWidth(): void {
// const chartContainer = this.el.nativeElement.querySelector('.chart-container');
// const chartContainer1 = this.el.nativeElement.querySelector('.chart-container1');
// const chartContainer2 = this.el.nativeElement.querySelector('.chart-container2');
// const chartContainer3 = this.el.nativeElement.querySelector('.chart-container3');
// const chart = new ApexCharts(chartContainer1, this.chartOptions);
// const chart1 = new ApexCharts(chartContainer, this.optionsCircle1);
// const chart2 = new ApexCharts(chartContainer2, this.chartOptions3);
// const chart3 = new ApexCharts(chartContainer3, this.chartOptions4);
// chart.render();
// chart2.render();
// chart1.render();
// chart3.render();
// }
}
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MyjobComponent } from './myjob.component'; import { MyjobComponent } from './myjob.component';
import { RouterModule, Routes } from '@angular/router';
import { QuillModule } from 'ngx-quill';
export const myjob: Routes = [
{
path: "myjob", children: [
{
//////////////MyJob/////////////////
path: 'home',
loadComponent: () =>
import('./home-common/home-common.component').then((m) => m.HomeCommonComponent),
},
{
path: 'member-manage',
loadComponent: () =>
import('./user-management/user-setting/user-setting.component').then((m) => m.UserSettingComponent),
},
{
path: 'manage-companys',
loadComponent: () =>
import('./company-manage/company-manage.component').then((m) => m.CompanyManageComponent),
},
{
path: 'manage-articles',
loadComponent: () =>
import('./article-manage/article-manage.component').then((m) => m.ArticleManageComponent),
},
{
path: 'admin-manage',
loadComponent: () =>
import('./admin-manage/admin-manage.component').then((m) => m.AdminManageComponent),
},
{
path: 'pdpa-manage',
loadComponent: () =>
import('./pdpa-manage/pdpa-manage.component').then((m) => m.PdpaManageComponent),
},
{
path: 'company-departments',
loadComponent: () =>
import('./company-department/company-department.component').then((m) => m.CompanyDepartmentComponent),
},
{
path: 'country-registration',
loadComponent: () =>
import('./company-department/country-registration/country-registration.component').then((m) => m.CountryRegistrationComponent),
},
{
path: 'category-company',
loadComponent: () =>
import('./company-department/category-company/category-company.component').then((m) => m.CategoryCompanyComponent),
},
{
path: 'degree-manage',
loadComponent: () =>
import('./company-department/degree-manage/degree-manage.component').then((m) => m.DegreeManageComponent),
},
{
path: 'job-types',
loadComponent: () =>
import('./company-department/job-type/job-type.component').then((m) => m.JobTypeComponent),
},
{
path: 'provinces',
loadComponent: () =>
import('./company-department/province/province.component').then((m) => m.ProvinceComponent),
},
{
path: 'admin-manage',
loadComponent: () =>
import('./admin-manage/admin-manage.component').then((m) => m.AdminManageComponent),
},
{
path: 'position',
loadComponent: () =>
import('./company-department/company-position/company-position.component').then((m) => m.CompanyPositionComponent),
},
{
path: 'career-cluster',
loadComponent: () =>
import('./company-department/career-cluster/career-cluster.component').then((m) => m.CareerClusterComponent),
},
]
}
]
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule CommonModule,
RouterModule.forChild(myjob),
QuillModule.forRoot(),
], ],
declarations: [MyjobComponent] declarations: [MyjobComponent],
exports: [RouterModule],
}) })
export class MyjobModule { } export class MyjobModule {
static routes = myjob;
}
.page {
display: flex;
height: 100%;
flex-direction: column;
}
\ No newline at end of file
<app-page-header [title]="'จัดการข้อมูลส่วนบุคคล'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'จัดการข้อมูลส่วนบุคคล'"></app-page-header>
<div class="block-main-content px-8 py-2">
<div class="page">
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header flex justify-between items-center flex-wrap gap-4">
<!-- ฝั่งซ้าย -->
<div class="flex items-center gap-3">
<div class="box-title">
{{ 'Edit Version' | translate }}
<span class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">
{{ itemsList.length }}
</span>
</div>
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="onBackPage()">
<i class="ti ti-chevron-left"></i>
{{ "Back" | translate }}
</button>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Consent List' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2"
*ngIf="someSelected" (click)="deleteSelect()"><i
class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาสมาชิก"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="ti-modal-body-content " style="margin-top: 10px;">
<div class="sm:grid grid-cols-12 gap-x-6 space-y-4 lg:space-y-0">
<div
class="col-span-12 lg:col-span-5 sm:inline-flex sm:items-center space-y-2 sm:space-y-0 sm:space-x-3 w-full rtl:space-x-reverse"
style="margin-left: 10%;">
<label class="w-56 ti-form-label mb-0 text-primary font-bold">{{"Version" | translate}}
*</label>
<input type="text" class="my-auto ti-form-input w-full bg-input-readonly" readonly>
</div>
</div>
<div class="sm:grid grid-cols-12 gap-x-6 space-y-4 lg:space-y-0 mt-1">
<div
class="col-span-12 lg:col-span-5 sm:inline-flex sm:items-center space-y-2 sm:space-y-0 sm:space-x-3 w-full rtl:space-x-reverse"
style="margin-left: 10%;">
<label class="w-56 ti-form-label mb-0 text-primary font-bold">{{"Start Date" | translate}} *</label>
<input type="text" class="my-auto ti-form-input w-full">
</div>
<div
class="col-span-12 lg:col-span-5 sm:inline-flex sm:items-center space-y-2 sm:space-y-0 sm:space-x-3 w-full rtl:space-x-reverse"
style="margin-left: 10%;">
<label class="w-56 ti-form-label mb-0 text-primary font-bold">{{"End Date" | translate}}</label>
<input type="text" class="ti-form-input w-full">
</div>
</div>
<div class="body-content mt-8">
<div class="!page">
<nav class="flex rtl:space-x-reverse space-x-2 border-b border-gray-200">
<a (click)="currentTab=1"
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="card-type-item-1" data-hs-tab="#card-type-1"
aria-controls="card-type-1">
ไทย
</a>
<a (click)="currentTab=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"
href="javascript:void(0);" id="card-type-item-2" data-hs-tab="#card-type-2"
aria-controls="card-type-2">
อังกฤษ
</a>
<a (click)="currentTab=3"
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="card-type-item-3" data-hs-tab="#card-type-3"
aria-controls="card-type-3">
จีน
</a>
</nav>
<div class="pt-50px">
<div *ngIf="currentTab==1" id="card-type-1" role="tabpanel" aria-labelledby="card-type-item-1">
<quill-editor [modules]="quillConfig" theme="snow"
>
</quill-editor>
</div>
<div *ngIf="currentTab==2" id="card-type-2" role="tabpanel" aria-labelledby="card-type-item-2">
<quill-editor [modules]="quillConfig" theme="snow"
>
</quill-editor>
</div>
<div *ngIf="currentTab==3" id="card-type-3" role="tabpanel" aria-labelledby="card-type-item-3">
<quill-editor [modules]="quillConfig" theme="snow"
>
</quill-editor>
</div>
<!-- <div *ngIf="currentTab==2" id="card-type-2" class="hidden" role="tabpanel"
aria-labelledby="card-type-item-2">
<app-sub-grade-registration [dataSelect]="dataSelect"
(sendDataSelect)="dataSelect=$event"></app-sub-grade-registration>
</div> -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
<!-- {{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('User' | translate) }} -->
สร้างเวอร์ชั่น
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'version' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': action === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="consent.version" [readonly]="action === 'edit'">
<div class="text-danger" *ngIf="!consent.version">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'วันที่เริ่ม' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="consent.startDate">
<div class="text-danger" *ngIf="!consent.startDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'วันที่สินสุด' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="consent.endDate">
<div class="text-danger" *ngIf="!consent.endDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="choices-multiple-remove-button2" id="choices-multiple-remove-button2" placeholder=""
[(ngModel)]="consent.status">
<ng-option [value]="0">{{'Unactive' | translate}}</ng-option>
<ng-option [value]="1">{{'Active' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { PdpaConfigComponent } from './pdpa-config.component';
describe('PdpaConfigComponent', () => {
let component: PdpaConfigComponent;
let fixture: ComponentFixture<PdpaConfigComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PdpaConfigComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PdpaConfigComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { Router } from "@angular/router";
import { SharedModule } from "../../../../shared/shared.module";
import { MyPdpaConsentModel, PdpaConsentModel, PdpaModel } from "../../../models/pdpa.model";
import { PdpaService } from "../../../services/pdpa.service";
import { TokenService } from "../../../../shared/services/token.service";
import { QuillModule } from "ngx-quill";
@Component({
selector: 'app-pdpa-config',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
ReactiveFormsModule,
MatPaginator,
FileUploadModule,
QuillModule
],
templateUrl: './pdpa-config.component.html',
styleUrl: './pdpa-config.component.css'
})
export class PdpaConfigComponent {
quillConfig = {
toolbar: [
['link'], // เพิ่มปุ่มลิงก์
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'align': [] }],
['clean'], // remove formatting button
]
};
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@Input() pdpaconfig: PdpaConsentModel = new MyPdpaConsentModel({})
@Output() sendEdit: EventEmitter<boolean> = new EventEmitter<boolean>();
currentTab = 1
edit = false
onBackPage() {
this.sendEdit.emit(false)
}
action = "new";
allSelected = false;
someSelected = false;
confirmPassword = ""
itemsList: MyPdpaConsentModel[] = []
filterList: MyPdpaConsentModel[] = []
consent: MyPdpaConsentModel = new MyPdpaConsentModel()
selectedItems = new Map<string, boolean>();
roleList: MyPdpaConsentModel[] = []
empList: MyPdpaConsentModel[] = []
descName = 'engName'
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add"
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private pdpaService: PdpaService, public translate: TranslateService, private tokenService: TokenService, private router: Router) {
}
ngOnInit(): void {
this.pdpaService.getConfigList().subscribe(res => {
this.itemsList = res.map(item => new MyPdpaConsentModel(item, this.translate));
this.filterList = [...this.itemsList];
});
}
editVersion(version: string) {
this.router.navigate(['/admin/pdpa-config/edit', version]); // ไปอีกหน้าหนึ่ง
}
createNewVersion() {
this.router.navigate(['/admin/pdpa-config/new']);
}
deleteVersion(version: string) {
swal({
title: "ยืนยันลบเวอร์ชัน?",
text: version,
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ลบ"]
}).then(confirm => {
if (confirm) {
this.pdpaService.deleteConfig(version).subscribe(() => {
swal("สำเร็จ", "ลบเวอร์ชันเรียบร้อย", "success");
this.ngOnInit();
});
}
});
}
filter(v: string): MyPdpaConsentModel[] {
const search = v.toLowerCase();
return this.itemsList.filter(x =>
x.version?.toLowerCase().includes(search) ||
x.startDate?.toLowerCase().includes(search) ||
x.endDate?.toLowerCase().includes(search) ||
x.status?.toLowerCase().includes(search)
);
}
delete(item: PdpaModel) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.pdpaService.deletePost(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit()
})
}
});
}
new() {
this.action = 'add'
this.consent = new MyPdpaConsentModel()
}
view(item: PdpaModel) {
this.action = 'edit'
this.confirmPassword = ''
this.consent = new MyPdpaConsentModel(item.pdpa, this.translate);
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
console.log(this.consent);
// if (this.action == 'add') {
// this.pdpaService.postPdpa(this.consent).subscribe(result => {
// console.log(result)
// swal("Save Success!!", "บันทึกข้อมูลสมาชิก", "success");
// this.ngOnInit()
// this.childModal?.nativeElement.click()
// })
// } else if (this.action == 'edit') {
// this.pdpaService.postPdpa(this.consent).subscribe(result => {
// console.log(result)
// swal("Update Success!!", "บันทึกข้อมูลสมาชิก", "success");
// this.ngOnInit()
// this.childModal?.nativeElement.click()
// })
// }
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.version, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.version));
}
onCheckboxChange(version: string) {
const isSelected = this.selectedItems.get(version) || false;
this.selectedItems.set(version, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.version));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.version));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const user = this.itemsList.find(user => user.version === version) as MyPdpaConsentModel;
if (user) {
employeeInfo += `${this.translate.instant('version')}: ${user.version}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const user = this.itemsList.find(user => user.version === version);
if (user) {
this.pdpaService.deletePost(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
// adjustSelect(status: number) {
// let title = "Are you sure?"
// let employeeInfo = ''; // ตัวแปรสำหรับเก็บข้อมูลพนักงาน
// this.selectedItems.forEach((isSelected, version) => {
// if (isSelected) {
// const user = this.itemsList.find(user => user.version === version);
// if (user) {
// employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
// }
// }
// });
// swal({
// title: title,
// text: employeeInfo,
// icon: "warning",
// dangerMode: false,
// buttons: ["Cancel", "Confirm"],
// })
// .then((willDelete: any) => {
// if (willDelete) {
// this.selectedItems.forEach((isSelected, version) => {
// if (isSelected) {
// const user = this.itemsList.find(user => user.version === version);
// if (user) {
// user.pdpa.status = status
// this.pdpaService.postPdpa(user).subscribe(result => {
// swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// this.ngOnInit();
// });
// }
// }
// });
// }
// });
// }
filterEmp(empId: string) {
this.consent = this.empList.filter(e => e.version == empId)[0]
}
}
.page {
display: flex;
height: auto;
flex-direction: column;
}
/* Base styling for the modal body content */
.ti-modal-body-content {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Form labels */
.ti-form-label {
font-size: 0.95rem;
color: #333;
}
/* Form inputs */
.ti-form-input {
border: 1px solid #d1d5db;
border-radius: 4px;
padding: 0.6rem 1rem;
font-size: 1rem;
transition: all 0.2s ease-in-out;
}
.ti-form-input:focus {
outline: none;
border-color: #3b82f6; /* Example primary color */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
}
/* Read-only input styling */
.bg-input-readonly {
background-color: #e5e7eb;
cursor: not-allowed;
}
/* Error text */
.text-danger {
color: #ef4444;
}
/* Tab button styling */
.tab-btn {
display: flex;
justify-content: center;
align-items: center;
width: 120px; /* Consistent width for tabs */
padding: 0.75rem 1rem;
border: 1px solid #d1d5db;
border-bottom: none; /* Remove bottom border for active tab effect */
border-top-left-radius: 4px;
border-top-right-radius: 4px;
font-size: 0.95rem;
font-weight: 500;
text-align: center;
color: #6b7280;
transition: all 0.2s ease-in-out;
text-decoration: none; /* Remove underline from anchor tags */
}
.tab-btn:hover {
color: #111827;
background-color: #f3f4f6;
}
/* Active tab styling */
.tab-btn.hs-tab-active {
background-color: #3b82f6; /* Example primary color */
border-color: #3b82f6;
color: #ffffff;
}
/* Custom primary color (replace with your actual primary color if different) */
.text-primary {
color: #3b82f6;
}
.bg-primary {
background-color: #3b82f6;
}
\ No newline at end of file
<ng-container *ngIf="!edit">
<app-page-header [title]="'จัดการ PDPA'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการ PDPA'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2" (click)="new()"
data-hs-overlay="#modal-detail"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Add Version' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2"
*ngIf="someSelected" (click)="adjustSelect(1)"><i
class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาเวอร์ชั่น"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Version' | translate}}</th>
<th scope="col" class="text-start">{{ 'Start Date' | translate}}</th>
<th scope="col" class="text-start">{{ 'End Date' | translate}}</th>
<th scope="col" class="text-start">{{ 'Status' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.version)" (change)="onCheckboxChange(item.version)"
aria-label="..." value="">
</td>
<td>
<div>
<span class="block">{{item.version}}</span>
</div>
</td>
<td>
<div>
<span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.startDate| date
: 'dd/MM/yyyy hh:mm a' : '+0000'}}</span>
</div>
</td>
<td>
<div>
<span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.endDate| date :
'dd/MM/yyyy hh:mm a' : '+0000'}}</span>
</div>
</td>
<td> <span
class="badge bg-{{ item.status == '1' ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="view(item)"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deleteVersion(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Add Version Oldest -->
<!-- <div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('User' | translate) }}
สร้างเวอร์ชั่น
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'version' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': modalStatus === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="pdpa.version" [readonly]="modalStatus === 'edit'">
<div class="text-danger" *ngIf="!pdpa.version">
{{'{{'Please fill in information' | translate}}' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'วันที่เริ่ม' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="pdpa.startDate">
<div class="text-danger" *ngIf="!pdpa.startDate">
{{'{{'Please fill in information' | translate}}' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'วันที่สินสุด' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="pdpa.endDate">
<div class="text-danger" *ngIf="!pdpa.endDate">
{{'{{'Please fill in information' | translate}}' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="choices-multiple-remove-button2" id="choices-multiple-remove-button2" placeholder=""
[(ngModel)]="pdpa.status">
<ng-option [value]="0">{{'Unactive' | translate}}</ng-option>
<ng-option [value]="1">{{'Active' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" class="ti-btn bg-primary text-white !font-medium">{{'Save' |
translate}}</button>
</div>
</div>
</div>
</div> -->
<!-- End:: Add Version Oldest -->
<ng-template #modalDetail let-modal>
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header flex justify-between items-center p-5">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('Version' | translate) }}
:
<span class="text-danger" *ngIf="pdpa.version">({{ pdpa.version }})</span>
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(click)="modalRef.close()" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body-content pt-6 pr-6 pl-6 pb-3 mb-4">
<!-- <div class="flex items-end justify-start md:justify-end">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full w-full md:w-auto"
(click)="openModalConsent()" data-hs-overlay="#modal-detail">
<i class="ri-add-line font-semibold align-middle"></i>
{{ 'Consent List' | translate }}
</a>
</div> -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
<div class="flex flex-col">
<label class="ti-form-label mb-2 text-primary font-bold">{{'Version' | translate}}
<span class="text-danger">*
<ng-container *ngIf="modalStatus=='add'&&checkPrimary()">
เวอร์ชั่นซ้ำ
</ng-container>
</span>
</label>
<input type="number" class="ti-form-input w-full" [(ngModel)]="pdpa.version" />
<div class="text-danger text-sm mt-1" *ngIf="!pdpa.version">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="flex flex-col">
<label class="ti-form-label mb-2 text-primary font-bold">{{ 'Status' | translate }} </label>
<div class="flex items-center space-x-6">
<label class="inline-flex items-center space-x-2">
<input type="radio" name="status" [(ngModel)]="pdpa.status" value="1" />
<span>{{ 'Active' | translate }}</span>
</label>
<label class="inline-flex items-center space-x-2">
<input type="radio" name="status" [(ngModel)]="pdpa.status" value="0" />
<span>{{ 'Unactive' | translate }}</span>
</label>
</div>
<div class="text-danger text-sm mt-1" *ngIf="pdpa.status === null || pdpa.status === undefined">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="flex flex-col">
<label class="ti-form-label mb-2 text-primary font-bold">{{'Start Date' | translate}} </label>
<input type="datetime-local" class="ti-form-input w-full" [(ngModel)]="pdpa.startDate"
max="9999-12-31T23:59" />
<div class="text-danger text-sm mt-1" *ngIf="!pdpa.startDate">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="flex flex-col">
<label class="ti-form-label mb-2 text-primary font-bold">{{'End Date' | translate}}</label>
<input type="datetime-local" class="ti-form-input w-full" [(ngModel)]="pdpa.endDate"
max="9999-12-31T23:59" />
<div class="text-danger text-sm mt-1" *ngIf="!pdpa.endDate">
{{'Please fill in information' | translate}}
</div>
</div>
</div>
<div class="body-content pt-0">
<nav class="flex space-x-2 border-b border-gray-200 mb-4">
<a (click)="currentTab = 1" class="tab-btn"
[ngClass]="{ '!bg-primary border-primary !text-white': currentTab === 1 }" href="javascript:void(0);">
{{ 'Thai' | translate }}
</a>
<a (click)="currentTab = 2" class="tab-btn"
[ngClass]="{ '!bg-primary border-primary !text-white': currentTab === 2 }" href="javascript:void(0);">
{{ 'Eng' | translate }}
</a>
<a (click)="currentTab = 3" class="tab-btn"
[ngClass]="{ '!bg-primary border-primary !text-white': currentTab === 3 }" href="javascript:void(0);">
{{ 'China' | translate }}
</a>
</nav>
<div>
<div *ngIf="currentTab == 1">
<quill-editor [modules]="quillConfig" [styles]="{ 'height': '500px', 'overflow-y': 'auto' }"
[(ngModel)]="pdpa.requestConsentThai" [ngModelOptions]="{ standalone: true }"
theme="snow"></quill-editor>
</div>
<div *ngIf="currentTab == 2">
<quill-editor [modules]="quillConfig" [styles]="{ 'height': '500px', 'overflow-y': 'auto' }"
[(ngModel)]="pdpa.requestConsentEng" [ngModelOptions]="{ standalone: true }"
theme="snow"></quill-editor>
</div>
<div *ngIf="currentTab == 3">
<quill-editor [modules]="quillConfig" [styles]="{ 'height': '500px', 'overflow-y': 'auto' }"
[(ngModel)]="pdpa.requestConsentChina" [ngModelOptions]="{ standalone: true }"
theme="snow"></quill-editor>
</div>
</div>
</div>
</div>
<div class="ti-modal-footer flex justify-center gap-4 mb-3">
<button type="button" class="hs-dropdown-toggle ti-btn bg-danger align-middle text-white !font-medium"
(click)="modalRef.close()" #closeModal>
{{'Cancel' | translate}}
</button>
<button type="button" (click)="save()" [disabled]="isSaving" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="
!pdpa.version ||
!pdpa.startDate ||
!pdpa.endDate
" [disabled]="
!pdpa.version ||
!pdpa.startDate ||
!pdpa.endDate
">
{{ isSaving ? ('Saving...' | translate) : ('Save' | translate) }}
</button>
</div>
</div>
</div>
</ng-template>
<ng-template #ConsentList let-modal>
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header flex justify-between items-center p-5">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{"Consent List | translate"}}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(click)="modalRefConsent.close()" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body-content pt-6 pr-6 pl-6 pb-3 mb-4">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Fullname' | translate}}</th>
<th scope="col" class="text-start">{{ 'Mobile' | translate}}</th>
<th scope="col" class="text-start">{{ 'Consent Date' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterListConsent.length > 0) {
@for(item of filterListConsent;track filterListConsent){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.profileId)" (change)="onCheckboxChange(item.profileId)"
aria-label="..." value="">
</td>
<td>
<div class="flex items-center">
<span class="avatar avatar-sm p-1 me-1 bg-light !rounded-full">
<img [src]="item.getPicture()" alt="" id="profile-img">
</span>
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="viewConsent(item)">
{{item.thFullName}}</a></p>
<!-- <p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p> -->
</div>
</div>
</td>
<td>
<div>
<span class="block"><i
class="ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.phoneCurrent}}</span>
</div>
</td>
<td><span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.consentDate
| date
: 'medium'}}</span>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsListConsent.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsListConsent.length > 0 && filterListConsent.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterListConsent.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterListConsent.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsListConsent.length : filterListConsent.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsListConsent.length : filterListConsent.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsListConsent.length : filterListConsent.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsListConsent.length : filterListConsent.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem]"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="ti-modal-footer flex justify-center gap-4 mb-3">
<button type="button" class="hs-dropdown-toggle ti-btn bg-danger align-middle text-white !font-medium"
(click)="modalRefConsent.close()" #closeModal>
{{'Previous' | translate}}
</button>
<!-- <button type="button" (click)="save()" [disabled]="isSaving"
class="ti-btn bg-primary text-white !font-medium">
{{ isSaving ? ('Saving...' | translate) : ('Save' | translate) }}
</button> -->
</div>
</div>
</div>
</ng-template>
</ng-container>
<ng-container *ngIf="edit">
<app-pdpa-config [pdpaconfig]="pdpaconfig" (sendEdit)="edit=false"></app-pdpa-config>
</ng-container>
\ No newline at end of file
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { PdpaManageComponent } from './pdpa-manage.component';
describe('PdpaManageComponent', () => {
let component: PdpaManageComponent;
let fixture: ComponentFixture<PdpaManageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PdpaManageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PdpaManageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, TemplateRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { SharedModule } from "../../../shared/shared.module";
import { UserProfileModel } from "../../models/user.model";
import { UserRoleModel } from "../../models/user-role-model";
import { TokenService } from "../../../shared/services/token.service";
import { environment } from "../../../../environments/environment";
import { PdpaService } from "../../services/pdpa.service";
import { Router } from "@angular/router";
import { PdpaConfigComponent } from "./pdpa-config/pdpa-config.component";
import { QuillModule } from "ngx-quill";
import { MatDialog } from "@angular/material/dialog";
import { MyPdpaConfigModel, PdpaConfigModel } from '../../models/pdpaConfig.model';
import { MyPdpaModel, PdpaModel } from "../../models/pdpa.model";
@Component({
selector: 'app-pdpa-manage',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule,
PdpaConfigComponent,
QuillModule
],
templateUrl: './pdpa-manage.component.html',
styleUrl: './pdpa-manage.component.css'
})
export class PdpaManageComponent {
quillConfig = {
toolbar: [
['link'],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'align': [] }],
['clean'],
]
};
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') modalDetail!: TemplateRef<any>;
@ViewChild('ConsentList') ConsentList!: TemplateRef<any>;
modalRef: any;
modalRefConsent: any;
pdpaconfig!: MyPdpaConfigModel;
edit = false
currentTab = 1
allSelected = false;
someSelected = false;
itemsList: MyPdpaConfigModel[] = []
filterList: MyPdpaConfigModel[] = []
pdpa: MyPdpaConfigModel = new MyPdpaConfigModel()
selectedItems = new Map<string, boolean>();
pageIndex = 0;
modalStatus: "add" | "edit" = "add"
isSaving = false;
consentList: PdpaModel[] = [];
itemsListConsent: MyPdpaModel[] = []
filterListConsent: MyPdpaModel[] = []
consent: MyPdpaModel = new MyPdpaModel()
isActiveExist: boolean = false;
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private pdpaService: PdpaService, public translate: TranslateService, private modal: MatDialog) {
}
ngOnInit(): void {
this.pdpaService.getConfigList().subscribe(res => {
this.itemsList = res.map(item => new MyPdpaConfigModel(item, this.translate));
this.filterList = [...this.itemsList];
});
this.pdpaService.getPdpaList().subscribe(res => {
this.consentList = res.map(item => new MyPdpaModel(item, this.translate));
this.filterListConsent = [...this.itemsListConsent];
});
}
filter(v: string): MyPdpaConfigModel[] {
const search = v.toLowerCase();
return this.itemsList.filter(x => {
const startDateStr = x.startDate ? new Date(x.startDate).toLocaleDateString() : '';
const endDateStr = x.endDate ? new Date(x.endDate).toLocaleDateString() : '';
const statusStr = x.status ? x.status.toString() : '';
return (x.version?.toLowerCase().includes(search)) ||
(startDateStr.toLowerCase().includes(search)) ||
(endDateStr.toLowerCase().includes(search)) ||
(statusStr.toLowerCase().includes(search));
});
}
new() {
this.modalStatus = 'add'
this.pdpa = new MyPdpaConfigModel();
this.openModal();
this.pdpa.status = "0";
}
view(item: MyPdpaConfigModel) {
this.modalStatus = 'edit';
this.pdpa = new MyPdpaConfigModel(item, this.translate);
this.formatDatesForDatetimeLocal(this.pdpa);
this.openModal();
}
viewConsent(item: MyPdpaModel) {
this.modalStatus = 'edit';
this.consent = new MyPdpaModel(item, this.translate);
}
private formatDatesForDatetimeLocal(consentModel: MyPdpaConfigModel): void {
if (consentModel.startDate) {
consentModel.startDate = consentModel.startDate.substring(0, 16);
}
if (consentModel.endDate) {
consentModel.endDate = consentModel.endDate.substring(0, 16);
}
}
// ----------------------------------------------------
save() {
this.pdpaService.getConfigList().subscribe({
next: configs => {
const isActiveExist = configs.some(cfg => cfg.status === "1" && cfg.version !== this.pdpa.version);
if (isActiveExist && this.pdpa.status === '1') {
// ถ้ามีเวอร์ชันอื่นที่เปิดใช้งานอยู่แล้ว และกำลังจะเปิดอีกเวอร์ชัน
swal({
title: "มีรายการที่เปิดใช้งานอยู่แล้ว",
text: "คุณกำลังจะเปิดใช้งานเวอร์ชันใหม่ แต่มีเวอร์ชันอื่นที่เปิดใช้งานอยู่แล้ว?",
icon: "warning",
buttons: ["ยกเลิก", "ยืนยัน"],
dangerMode: false,
}).then((confirm: boolean) => {
if (confirm) {
if (this.modalStatus === 'add') {
this.pdpaService.postConfig(this.pdpa).subscribe(() => {
swal("บันทึกสำเร็จ", "บันทึกเวอร์ชั่นสำเร็จแล้ว", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
});
} else if (this.modalStatus === 'edit') {
const respone = new MyPdpaConfigModel(this.pdpa);
this.pdpaService.update(respone).subscribe(() => {
swal("อัปเดตสำเร็จ", "บันทึกเวอร์ชั่นสำเร็จแล้ว", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
});
}
}
});
} else {
// กรณีทั่วไป
swal({
title: "ยืนยันการบันทึก",
text: "คุณต้องการบันทึกหรือไม่?",
icon: "warning",
buttons: ["ยกเลิก", "ยืนยัน"],
dangerMode: false,
}).then((willSave: boolean) => {
if (willSave) {
if (this.modalStatus === 'add') {
this.pdpaService.postConfig(this.pdpa).subscribe(() => {
swal("บันทึกสำเร็จ", "บันทึกเวอร์ชั่นสำเร็จแล้ว", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
});
} else if (this.modalStatus === 'edit') {
const respone = new MyPdpaConfigModel(this.pdpa);
this.pdpaService.update(respone).subscribe(() => {
swal("อัปเดตสำเร็จ", "บันทึกเวอร์ชั่นสำเร็จแล้ว", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
});
}
}
});
}
},
error: (error) => {
console.error('Error: ', error);
}
});
}
deleteVersion(item: PdpaConfigModel) {
const versionText = `${this.translate.instant('Version')}: ${item.version || 'เวอร์ชั่นที่จะลบเป็นค่าว่าง'}`;
swal({
title: "Are you sure?",
text: `Confirm to delete :\n${versionText}\!`,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
}).then((willDelete: any) => {
if (willDelete) {
this.pdpaService.deleteConfig(item.version).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
});
}
deleteSelect() {
let pdpaConfig = '';
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version) as MyPdpaConfigModel;
if (pdpa) {
pdpaConfig += `${this.translate.instant('Version')}: ${pdpa.version || 'เวอร์ชั่นที่จะลบเป็นค่าว่าง'}\n`;
}
}
});
swal({
title: "Are you sure?",
text: pdpaConfig,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version);
if (pdpa) {
this.pdpaService.deleteConfig(version).subscribe(result => {
swal("Delete Success!!", "ลบข้อมูลที่เลือกสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
adjustSelect(status: number) {
this.pdpaService.getConfigList().subscribe({
next: configs => {
this.isActiveExist = configs.some(cfg => cfg.status === "1" && cfg.version !== this.pdpa.version);
if (status === 1) {
let isSelectedAlreadyActive = false;
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(item => item.version === version);
if (pdpa && pdpa.status === '1') {
isSelectedAlreadyActive = true;
}
}
});
if (isSelectedAlreadyActive) {
// แจ้งเตือนว่ามีเวอร์ชันที่เลือกเปิดอยู่แล้ว
swal({
title: "เวอร์ชันนี้เปิดใช้งานอยู่แล้ว",
text: "หนึ่งในเวอร์ชันที่คุณเลือกได้ถูกเปิดใช้งานอยู่แล้ว คุณต้องการดำเนินการต่อหรือไม่?",
icon: "info",
buttons: ["ยกเลิก", "ยืนยัน"],
dangerMode: false,
}).then((confirm: boolean) => {
if (confirm) {
this.proceedUpdate(status);
}
});
return;
}
if (this.isActiveExist) {
// แจ้งเตือนว่ามีเวอร์ชันอื่นเปิดใช้งานอยู่แล้ว
swal({
title: "มีเวอร์ชันอื่นที่เปิดใช้งานอยู่แล้ว",
text: "คุณกำลังจะเปิดใช้งานเวอร์ชันใหม่ แต่มีเวอร์ชันอื่นที่เปิดใช้งานอยู่แล้ว?",
icon: "warning",
buttons: ["ยกเลิก", "ยืนยัน"],
dangerMode: false,
}).then((confirm: boolean) => {
if (confirm) {
let pdpaConfig = ''; // เก็บข้อมูลเวอร์ชันที่เลือก
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version);
if (pdpa) {
pdpaConfig += `${this.translate.instant('Version')}: ${pdpa.version}\n`;
}
}
});
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version);
if (pdpa) {
const cleanPdpa = {
version: pdpa.version,
startDate: pdpa.startDate,
endDate: pdpa.endDate,
status: status.toString(),
requestConsentThai: pdpa.requestConsentThai,
requestConsentEng: pdpa.requestConsentEng,
requestConsentChina: pdpa.requestConsentChina
};
this.pdpaService.update(cleanPdpa).subscribe(result => {
swal("บันทึกสำเร็จ!", "ข้อมูลถูกบันทึกเรียบร้อยแล้ว", "success");
this.ngOnInit(); // รีเฟรชข้อมูลหลังจากอัปเดต
});
}
}
});
}
});
return;
}
}
this.proceedUpdate(status);
},
error: err => {
console.error('Failed to load config list', err);
}
});
}
proceedUpdate(status: number) {
let title = "คุณแน่ใจหรือไม่?";
let pdpaConfig = ''; // เก็บข้อมูลเวอร์ชันที่เลือก
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version);
if (pdpa) {
pdpaConfig += `${this.translate.instant('Version')}: ${pdpa.version}\n`;
}
}
});
swal({
title: title,
text: pdpaConfig,
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willProceed: any) => {
if (willProceed) {
this.selectedItems.forEach((isSelected, version) => {
if (isSelected) {
const pdpa = this.itemsList.find(pdpa => pdpa.version === version);
if (pdpa) {
const cleanPdpa = {
version: pdpa.version,
startDate: pdpa.startDate,
endDate: pdpa.endDate,
status: status.toString(),
requestConsentThai: pdpa.requestConsentThai,
requestConsentEng: pdpa.requestConsentEng,
requestConsentChina: pdpa.requestConsentChina
};
this.pdpaService.update(cleanPdpa).subscribe(result => {
swal("บันทึกสำเร็จ!", "ข้อมูลถูกบันทึกเรียบร้อยแล้ว", "success");
this.ngOnInit(); // รีเฟรชข้อมูลหลังจากอัปเดต
});
}
}
});
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.version, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.version));
}
onCheckboxChange(version: string) {
const isSelected = this.selectedItems.get(version) || false;
this.selectedItems.set(version, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.version));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.version));
}
openModal() {
this.modalRef = this.modal.open(this.modalDetail, {
width: '1700px',
height: '1000px'
})
}
closeModal() {
this.modalRef.close()
}
openModalConsent() {
this.modalRefConsent = this.modal.open(this.ConsentList, {
width: '1500px',
height: '750px'
})
}
closeModalConsent() {
this.modalRefConsent.close()
}
filterEmp(empId: string) {
this.pdpa = this.itemsList.filter(e => e.version == empId)[0]
}
checkPrimary() {
return this.itemsList.find(x => x.version == this.pdpa.version)
}
}
\ No newline at end of file
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'app-user-management',
standalone: true,
imports: [
CommonModule,
],
template: `<p>user-management works!</p>`,
styleUrl: './user-management.component.css',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UserManagementComponent { }
<app-page-header [title]="'จัดการสมาชิก'" [activeTitle]="'ผู้ดูแลระบบ'" [title1]="'จัดการสมาชิก'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}} <span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle">{{itemsList.length}}</span>
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(click)="modalStatus='add';new()" data-hs-overlay="#modal-detail"><i
class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect(1)"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect(0)"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-danger-full me-2" *ngIf="someSelected"
(click)="deleteSelect()"><i class="ri-delete-bin-line font-semibold align-middle"></i>{{ 'Delete' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาสมาชิก"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div>
<!-- <div>
<input class="form-control form-control" type="text" placeholder="กรองตามบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div> -->
<!-- <a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul> -->
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder">
<th scope="col" class="!text-start">
<input class="form-check-input check-all" type="checkbox" id="all-products"
(change)="toggleAll($event)" [checked]="allSelected" aria-label="...">
</th>
<th scope="col" class="text-start">{{ 'Candidate ID' | translate}}</th>
<th scope="col" class="text-start">{{ 'Fullname' | translate}}</th>
<th scope="col" class="text-start">{{ 'Email' | translate}}</th>
<!-- <th scope="col" class="text-start">{{ 'User Group' | translate}}</th> -->
<th scope="col" class="text-start">{{ 'Status' | translate}}</th>
<th scope="col" class="text-start">{{ 'Update Date' | translate}}</th>
<th scope="col" class="text-start">{{ 'Action' | translate}}</th>
<th scope="col" class="text-start"></th>
</tr>
</thead>
<tbody>
@if (filterList.length > 0) {
@for(item of filterList;track filterList){
<tr class="border border-defaultborder dark:border-defaultborder/10">
<td class="product-checkbox"><input class="form-check-input" type="checkbox"
[checked]="selectedItems.get(item.candidateId)" (change)="onCheckboxChange(item.candidateId)"
aria-label="..." value="">
</td>
<td>
<div class="flex items-center">
<span class="avatar avatar-sm p-1 me-1 bg-light !rounded-full">
<img [src]="item.getPicture()" alt="" id="profile-img">
</span>
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="view(item)">
{{item.candidateId}}</a></p>
<!-- <p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p> -->
</div>
</div>
</td>
<!-- <td>
<div class="flex">
<div class="ms-2">
<p class="font-semibold mb-0 flex items-center text-primary"><a (click)="view(item)"
data-hs-overlay="#modal-detail">
{{item.username}}</a></p>
<p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p>
</div>
</div>
</td> -->
<td> {{item.getFullname()}}</td>
<td>
<div>
<span class="block mb-1"><i
class="ri-mail-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.email}}</span>
</div>
</td>
<!-- <td> <span
class="badge bg-{{ item.role == 0 ? 'primary' : 'info'}} text-white">{{item.getRole()}}</span>
</td> -->
<td> <span
class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span>
</td>
<td><span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.lastModifiedDate|
date : 'dd/MM/yyyy hh:mm a' : '+0000'}}</span>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="modalStatus='edit';view(item)" data-hs-overlay="#modal-detail"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"><i
class="ri-pencil-line"></i></a>
<a aria-label="anchor" href="javascript:void(0);" (click)="delete(item)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
}
} @else {
<tr>
<td [attr.colspan]="6" class="text-center py-4">
<ng-container *ngIf="itemsList.length === 0 && !searchTerm">
<p>กำลังโหลดข้อมูล หรือไม่มีข้อมูลเลย...</p>
</ng-container>
<ng-container *ngIf="itemsList.length > 0 && filterList.length === 0 && searchTerm">
<p>ไม่พบข้อมูลที่ค้นหา...</p>
</ng-container>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto" *ngIf="filterList.length > 0">
<div class="mb-2 sm:mb-0">
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}} <i class="bi bi-arrow-right ms-2 font-semibold"></i>
</div>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0">
<li *ngIf="pageIndex>0" class="page-item {{pageIndex==0 ? 'disabled' : ''}}"><a
class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{'Previous' | translate}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex-1>0" (click)="pageIndex = pageIndex-2;updatePagedItems()">{{pageIndex-1}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(click)="pageIndex = pageIndex-1;updatePagedItems()">{{pageIndex}}</a></li>
<li class="page-item"><a class="page-link active px-3 py-[0.375rem]"
href="javascript:void(0);">{{pageIndex +1}}</a>
</li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{pageIndex +2}}</a></li>
<li class="page-item"><a class="page-link px-3 py-[0.375rem]" href="javascript:void(0);"
*ngIf="(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(click)="pageIndex = pageIndex+2;updatePagedItems()">{{pageIndex +3}}</a></li>
<li *ngIf="(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class="page-item"><a class="page-link px-3 py-[0.375rem] cursor-pointer"
(click)="pageIndex = pageIndex+1;updatePagedItems()">{{'Next' |
translate}}</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div id="modal-detail" class="hs-overlay hidden ti-modal [--overlay-backdrop:static]">
<div class="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
<div class="ti-modal-content">
<div class="ti-modal-header">
<h6 class="modal-title text-[1rem] font-semibold text-defaulttextcolor" id="mail-ComposeLabel">
{{ (modalStatus == 'add' ? ('Create' | translate) : ('Edit' | translate)) + ' ' + ('User Information' |
translate) }}
</h6>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#modal-detail" #closeModal>
<span class="sr-only">{{'Close' | translate}}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4">
<div class="grid grid-cols-12 gap-4">
<div class="xl:col-span-12 col-span-12">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="selectModel.getPicture()" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input (click)="triggerFileInput()" ng2FileSelect [uploader]="uploaderProfile" type="file"
name="photo" [disabled]="action === 'edit'" class="absolute w-full h-full opacity-[0]"
id="profile-change">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-12 col-span-12" *ngIf="modalStatus=='edit'">
<label for="deal-title" class="form-label">{{'Candidate ID' | translate}}</label>
<input type="text" class="form-control" [ngClass]="{ '!bg-input-readonly': action === 'edit' }"
id="deal-title" placeholder="" [(ngModel)]="selectModel.candidateId" [readonly]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.candidateId">
{{'Please fill in information' | translate}}
</div>
</div>
<!-- <div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.password">
<div class="text-danger" *ngIf="!selectModel.password">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{'Confirm Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder="" [(ngModel)]="confirmPassword">
<div class="text-danger" *ngIf="!confirmPassword">
{{'Please fill in information' | translate}}
</div>
<div class="text-danger" *ngIf="confirmPassword && (confirmPassword != selectModel.password)">
{{'Password Not Match' | translate}}
</div>
</div> -->
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'Name(Thai)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.thFirstname">
<div class="text-danger" *ngIf="!selectModel.thFirstname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'Surname(Thai)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.thLastname">
<div class="text-danger" *ngIf="!selectModel.thLastname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'Name(Eng)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.engFirstname">
<div class="text-danger" *ngIf="!selectModel.engFirstname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='add'">
<label for="deal-title" class="form-label">{{'Surname(Eng)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.engLastname">
<div class="text-danger" *ngIf="!selectModel.engLastname">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='edit'">
<label for="deal-title" class="form-label">{{'Name-Surname(Thai)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.thFullName"
[disabled]="action === 'edit'">
<div class="text-danger" *ngIf="!selectModel.thFullName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='edit'">
<label for="deal-title" class="form-label">{{'Name-Surname(Eng)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [disabled]="action === 'edit'"
[(ngModel)]="selectModel.engFullName">
<div class="text-danger" *ngIf="!selectModel.engFullName">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-title" class="form-label">{{ 'Email' | translate }}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.email"
[disabled]="action === 'edit'" (ngModelChange)="onEmailChange($event)" />
<div class="text-danger" *ngIf="!selectModel.email">
{{ 'Please fill in information' | translate }}
</div>
<div class="text-danger" *ngIf="selectModel.email && (!selectModel.email.includes('@'))">
{{ 'Invalid email format @' | translate }}
</div>
<div class="text-danger"
*ngIf="selectModel.email && selectModel.email.includes('@') && !selectModel.email.split('@')[1]?.includes('.')">
{{ 'Invalid email format .' | translate }}
</div>
<div class="text-danger" *ngIf="isEmailDuplicate && action !== 'edit'">
{{ 'This email already exists' | translate }}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="action !== 'edit'">
<label for="password" class="form-label">{{'Password' | translate}}</label>
<input type="password" class="form-control" id="password" placeholder="" [(ngModel)]="password">
<div class="text-danger" *ngIf="!password">
{{ 'Please fill in information' | translate }}
</div>
</div>
<div class="xl:col-span-6 col-span-12" *ngIf="action !== 'edit'">
<label for="deal-title" class="form-label">{{'Confirm Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder="" [(ngModel)]="confirmPassword">
<div class="text-danger" *ngIf="!confirmPassword">
{{'Please fill in information' | translate}}
</div>
<div class="text-danger" *ngIf="confirmPassword && (confirmPassword != password)">
{{'Password Not Match' | translate}}
</div>
</div>
<!-- <div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'User Role' | translate}}</label>
<ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModel.role">
<ng-option [value]="0">{{'ผู้ใช้งานทั่วไป' | translate}}</ng-option>
<ng-option [value]="1">{{'ผู้ดูแลบริษัท' | translate}}</ng-option>
</ng-select>
</div> -->
<div class="xl:col-span-12 col-span-12">
<label class="form-label">{{'Status' | translate}}</label>
<ng-select name="choices-multiple-remove-button2" id="choices-multiple-remove-button2" placeholder=""
[disabled]="action === 'edit'" [(ngModel)]="selectModel.status">
<ng-option [value]="0">{{'Unactive' | translate}}</ng-option>
<ng-option [value]="1">{{'Active' | translate}}</ng-option>
</ng-select>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail">
{{'Cancel' | translate}}
</button>
<button type="button" *ngIf="modalStatus=='add'" (click)="save()"
class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="
!selectModel.thFirstname ||
!selectModel.thLastname ||
!selectModel.engFirstname ||
!selectModel.engLastname ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) ||
!password || !confirmPassword || (confirmPassword !== password)
" [disabled]="
!selectModel.thFirstname ||
!selectModel.thLastname ||
!selectModel.engFirstname ||
!selectModel.engLastname ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) ||
!password || !confirmPassword || (confirmPassword !== password)">
{{ 'Save' | translate }}
</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
\ No newline at end of file
import { CommonModule } from "@angular/common";
import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { SharedModule } from "../../../../shared/shared.module";
import { UserService } from "../../../services/user.service";
import { FormsModule } from "@angular/forms";
import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from "../../../../../environments/environment";
import { TokenService } from "../../../../shared/services/token.service";
import { RoleModel } from "../../../models/role.model";
import { AuthModel } from "../../../models/auth.model";
import { ProfileModel } from "../../../models/profile.model";
@Component({
selector: 'app-user-setting',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule,
FileUploadModule
],
templateUrl: './user-setting.component.html',
styleUrl: './user-setting.component.css'
})
export class UserSettingComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
@ViewChild('profileChangeInput') profileChangeInputRef!: ElementRef;
action = "new";
allSelected = false;
someSelected = false;
confirmPassword = ""
itemsList: ProfileModel[] = []
filterList: ProfileModel[] = []
selectModel: ProfileModel = new ProfileModel()
selectedItems = new Map<string, boolean>();
roleList: RoleModel[] = []
empList: ProfileModel[] = []
descName = 'engName'
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add"
existingEmails: ProfileModel[] = []
isEmailDuplicate = false;
password: string = '';
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.pageIndex = 0;
this.allSelected = false
this._searchTerm = val;
if (val != '') {
this.filterList = this.filter(val);
} else {
this.updatePagedItems()
}
}
_searchTerm = "";
constructor(private userService: UserService, public translate: TranslateService, private tokenService: TokenService) {
this.uploadConfig()
}
uploadConfig() {
this.uploaderProfile = new FileUploader({
url: environment.baseUrl + "/files/upload-image",
isHTML5: true,
authToken: this.tokenService.getToken()!,
});
this.uploaderProfile.onAfterAddingFile = (fileItem: FileItem) => {
fileItem.withCredentials = false;
this.uploadErrorMsg = "";
while (this.uploaderProfile!.queue.length > 1) {
this.uploaderProfile!.queue[0].remove();
}
if (fileItem.file.size > 5000000) {
this.uploadErrorMsg = "maximum file size 5mb.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
if (fileItem.file.type!.indexOf("image") === -1) {
this.uploadErrorMsg = "please upload image only.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
fileItem.isCancel = true;
return;
}
fileItem.upload();
};
this.uploaderProfile.onCompleteItem = (
item: FileItem,
response: string,
status: number,
headers: ParsedResponseHeaders
) => {
if (item.isSuccess) {
const res = JSON.parse(response);
console.log("res", res);
this.selectModel.picture = res.resultObject;
swal(res.message, "บันทึกสำเร็จ", "success");
} else {
this.uploadErrorMsg = "cannot upload file.";
swal("Opp!!", "ไม่สามารถอัพโหลดได้", "info");
}
};
}
ngOnInit(): void {
this.userService.getListsProfile().subscribe(result => {
this.itemsList = result.map(item => new ProfileModel(item, this.translate));
this.filterList = [...this.itemsList];
this.existingEmails = result;
});
}
onEmailChange(email: string) {
const lowerEmail = email.trim().toLowerCase();
this.isEmailDuplicate = this.existingEmails.some(
user => user.email && user.email.toLowerCase() === lowerEmail
);
}
filter(v: string): ProfileModel[] {
const search = v.toLowerCase();
return this.itemsList?.filter(x =>
x.candidateId?.toLowerCase().includes(search) ||
x.email?.toLowerCase().includes(search) ||
x.email?.toLowerCase().includes(search) ||
x.phoneCurrent?.toLowerCase().includes(search) ||
x.getStatus()?.toLowerCase().includes(search) ||
x.getName?.()?.toLowerCase().includes(search)
);
}
delete(item: ProfileModel) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!",
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes,Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.userService.put(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit()
})
}
});
}
new() {
this.action = 'add'
this.selectModel = new ProfileModel()
this.selectModel.status = 1;
}
view(item: ProfileModel) {
this.action = 'edit'
this.confirmPassword = ''
this.selectModel = new ProfileModel(item)
}
save() {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
}).then((willSave: any) => {
if (willSave) {
if (this.action === 'add') {
const body = new AuthModel();
body.username = this.selectModel.email;
body.password = this.password;
body.role = new RoleModel({ roleId: 'candidate' });
const rawProfile = { ...body.profile };
rawProfile.thFirstname = rawProfile.thFirstname || this.selectModel.thFirstname || "";
rawProfile.thLastname = rawProfile.thLastname || this.selectModel.thLastname || "";
rawProfile.engFirstname = rawProfile.engFirstname || this.selectModel.engFirstname || "";
rawProfile.engLastname = rawProfile.engLastname || this.selectModel.engLastname || "";
rawProfile.email = rawProfile.email || this.selectModel.email || "";
rawProfile.status = rawProfile.status ?? 1;
body.profile = new ProfileModel(rawProfile);
this.userService.register(body).subscribe({
next: res => {
if (this.selectModel.status === 1) {
swal("Save Success!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
} else {
swal("Save Failed", res?.message || "ไม่สามารถลงทะเบียนได้", "warning");
}
},
error: err => {
console.error('Error response:', err);
const errorMessage = err?.error?.message || err?.message || 'ไม่ทราบสาเหตุ';
if (errorMessage.includes('email')) {
swal("Save Failed", "อีเมลซ้ำหรือไม่ถูกต้อง", "warning");
} else {
swal("Error", errorMessage, "error");
}
}
});
} else if (this.action === 'edit') {
this.userService.update(this.selectModel).subscribe({
next: result => {
swal("Update Success!!", "บันทึกข้อมูลสมาชิก", "success");
this.ngOnInit();
this.childModal?.nativeElement.click();
},
error: err => {
swal("Error", "ไม่สามารถอัปเดตได้", "error");
}
});
}
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
this.filterList = this.itemsList.slice(startIndex, endIndex);
}
toggleAll(event: any) {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.candidateId ?? '', this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId ?? ''));
}
onCheckboxChange(candidateId: string) {
const isSelected = this.selectedItems.get(candidateId) || false;
this.selectedItems.set(candidateId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.candidateId ?? ''));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId ?? ''));
}
deleteSelect() {
let employeeInfo = '';
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
}
});
swal({
title: "Are you sure?",
text: employeeInfo,
icon: "warning",
dangerMode: true,
buttons: ["Cancel", "Yes, Delete it!"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
this.userService.put(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
adjustSelect(status: number) {
let title = "Are you sure?"
let employeeInfo = ''; // ตัวแปรสำหรับเก็บข้อมูลพนักงาน
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
}
});
swal({
title: title,
text: employeeInfo,
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
user.status = status
this.userService.update(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit();
});
}
}
});
}
});
}
filterEmp(empId: string) {
this.selectModel = this.empList.filter(e => e.candidateId == empId)[0]
}
triggerFileInput(): void {
if (this.profileChangeInputRef) {
this.profileChangeInputRef.nativeElement.click();
}
}
}
...@@ -353,7 +353,7 @@ ...@@ -353,7 +353,7 @@
</div> </div>
<div class=""> <div class="">
<a routerLink="/admin/member-manage" <a routerLink="/myjob/pdpa-manage"
class="p-4 items-center related-app block text-center rounded-sm hover:bg-gray-50 dark:hover:bg-black/20"> class="p-4 items-center related-app block text-center rounded-sm hover:bg-gray-50 dark:hover:bg-black/20">
<img src="./assets/images/logoallHR/logo_myjob.png" alt="miscrosoft" <img src="./assets/images/logoallHR/logo_myjob.png" alt="miscrosoft"
class="leading-[1.75] text-2xl !h-[1.75rem] align-middle flex justify-center mx-auto"> class="leading-[1.75] text-2xl !h-[1.75rem] align-middle flex justify-center mx-auto">
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
<img *ngIf="isCommonRoute" src="./assets/images/brand-logos/logo.png" alt="logo" width="100%"> <img *ngIf="isCommonRoute" src="./assets/images/brand-logos/logo.png" alt="logo" width="100%">
<img *ngIf="isMyportalRoute" src="./assets/images/logoallHR/mySkill-x.png" alt="logo" width="100%"> <img *ngIf="isMyportalRoute" src="./assets/images/logoallHR/mySkill-x.png" alt="logo" width="100%">
<img *ngIf="isMylearnRoute" src="./assets/images/logoallHR/mylearn-logo.png" alt="logo" width="100%"> <img *ngIf="isMylearnRoute" src="./assets/images/logoallHR/mylearn-logo.png" alt="logo" width="100%">
<img *ngIf="isMyJobRoute" src="./assets/images/brand-logos/logo.png" alt="logo" width="100%">
</a> </a>
......
...@@ -71,6 +71,7 @@ export class SidebarComponent { ...@@ -71,6 +71,7 @@ export class SidebarComponent {
isInstallerRoute: boolean = false; isInstallerRoute: boolean = false;
isMyportalRoute: boolean = false; isMyportalRoute: boolean = false;
isMylearnRoute: boolean = false; isMylearnRoute: boolean = false;
isMyJobRoute: boolean = false;
previousUrl: string = ''; previousUrl: string = '';
currentUrl: string = ''; currentUrl: string = '';
...@@ -110,7 +111,8 @@ export class SidebarComponent { ...@@ -110,7 +111,8 @@ export class SidebarComponent {
this.isCommonRoute = this.currentUrl.includes('/admin'); this.isCommonRoute = this.currentUrl.includes('/admin');
this.isInstallerRoute = this.currentUrl.includes('/company'); this.isInstallerRoute = this.currentUrl.includes('/company');
this.isMyportalRoute = this.currentUrl.includes('/myportal'); this.isMyportalRoute = this.currentUrl.includes('/myportal');
this.isMylearnRoute = this.currentUrl.includes('/mylearn') this.isMylearnRoute = this.currentUrl.includes('/mylearn');
this.isMyJobRoute = this.currentUrl.includes('/myjob');
this.menuitemsSubscribe$ = this.navServices.items.subscribe((items) => { this.menuitemsSubscribe$ = this.navServices.items.subscribe((items) => {
this.changeMenu() this.changeMenu()
}); });
...@@ -141,6 +143,7 @@ export class SidebarComponent { ...@@ -141,6 +143,7 @@ export class SidebarComponent {
this.isInstallerRoute = this.currentUrl.includes('/company'); this.isInstallerRoute = this.currentUrl.includes('/company');
this.isMyportalRoute = this.currentUrl.includes('/myportal'); this.isMyportalRoute = this.currentUrl.includes('/myportal');
this.isMylearnRoute = this.currentUrl.includes('/mylearn') this.isMylearnRoute = this.currentUrl.includes('/mylearn')
this.isMyJobRoute = this.currentUrl.includes('/myjob')
this.checkUrlChanges() this.checkUrlChanges()
// Log to console for verification // Log to console for verification
console.log('Initial URL:', this.currentUrl); console.log('Initial URL:', this.currentUrl);
...@@ -167,7 +170,8 @@ export class SidebarComponent { ...@@ -167,7 +170,8 @@ export class SidebarComponent {
(this.previousUrl.includes('/company') && this.currentUrl.includes('/admin')) || (this.previousUrl.includes('/company') && this.currentUrl.includes('/admin')) ||
(this.previousUrl.includes('/admin') && this.currentUrl.includes('/company')) || (this.previousUrl.includes('/admin') && this.currentUrl.includes('/company')) ||
(this.previousUrl.includes('/myprotal')&& this.currentUrl.includes('/myprotal')) || (this.previousUrl.includes('/myprotal')&& this.currentUrl.includes('/myprotal')) ||
(this.previousUrl.includes('/mylearn')&& this.currentUrl.includes('/mylearn')) (this.previousUrl.includes('/mylearn')&& this.currentUrl.includes('/mylearn')) ||
(this.previousUrl.includes('/myjob')&& this.currentUrl.includes('/myjob'))
) { ) {
console.log('URL changed between /installer and /admin.'); console.log('URL changed between /installer and /admin.');
// Implement any logic needed when changing between /installer and /admin // Implement any logic needed when changing between /installer and /admin
...@@ -177,7 +181,8 @@ export class SidebarComponent { ...@@ -177,7 +181,8 @@ export class SidebarComponent {
this.isCommonRoute = this.currentUrl.includes('/admin'); this.isCommonRoute = this.currentUrl.includes('/admin');
this.isInstallerRoute = this.currentUrl.includes('/company'); this.isInstallerRoute = this.currentUrl.includes('/company');
this.isMyportalRoute = this.currentUrl.includes('/myportal'); this.isMyportalRoute = this.currentUrl.includes('/myportal');
this.isMylearnRoute = this.currentUrl.includes('/mylearn') this.isMylearnRoute = this.currentUrl.includes('/mylearn');
this.isMyJobRoute = this.currentUrl.includes('/myjob');
// Log to console for verification // Log to console for verification
console.log('Current URL:', this.currentUrl); console.log('Current URL:', this.currentUrl);
...@@ -206,6 +211,8 @@ export class SidebarComponent { ...@@ -206,6 +211,8 @@ export class SidebarComponent {
this.menuItems = this.navServices.getMyportalMenu(); this.menuItems = this.navServices.getMyportalMenu();
} else if (this.isMylearnRoute){ } else if (this.isMylearnRoute){
this.menuItems = this.navServices.getMylearnMenu(); this.menuItems = this.navServices.getMylearnMenu();
} else if (this.isMyJobRoute){
this.menuItems = this.navServices.getMyJobMenu();
}else{ }else{
this.menuItems = this.navServices.getCommonMenu() this.menuItems = this.navServices.getCommonMenu()
} }
......
...@@ -30,6 +30,7 @@ import { CommonManageModule } from '../../DPU/common/common.module'; ...@@ -30,6 +30,7 @@ import { CommonManageModule } from '../../DPU/common/common.module';
import { CompanyManagementModule } from '../../DPU/company-management/company-management.module'; import { CompanyManagementModule } from '../../DPU/company-management/company-management.module';
import { MyskillXModule } from '../../DPU/myskill-x/myskill-x.module'; import { MyskillXModule } from '../../DPU/myskill-x/myskill-x.module';
import { MylearnModule } from '../../DPU/mylearn/mylearn.module'; import { MylearnModule } from '../../DPU/mylearn/mylearn.module';
import { MyjobModule } from '../../DPU/myjob/myjob.module';
export const content: Routes = [ export const content: Routes = [
...@@ -65,7 +66,8 @@ export const content: Routes = [ ...@@ -65,7 +66,8 @@ export const content: Routes = [
...CommonManageModule.routes, ...CommonManageModule.routes,
...CompanyManagementModule.routes, ...CompanyManagementModule.routes,
...MyskillXModule.routes, ...MyskillXModule.routes,
...MylearnModule.routes ...MylearnModule.routes,
...MyjobModule.routes,
] ]
} }
......
...@@ -296,5 +296,49 @@ export class NavService implements OnDestroy { ...@@ -296,5 +296,49 @@ export class NavService implements OnDestroy {
]; ];
} }
getMyJobMenu() {
return [
// Dashboard
{ headTitle: 'MyJob' },
{
icon: 'news bx-flip-horizontal',
path: '/myjob/pdpa-manage',
title: 'จัดการ PDPA',
type: 'link',
},
{
icon: 'receipt',
path: '/myjob/manage-articles',
title: 'จัดการบทความ',
type: 'link',
},
{
icon: 'user',
path: '/myjob/company-departments',
title: 'จัดการผู้ใช้',
type: 'sub',
children: [
{ path: '/myjob/manage-companys', title: 'จัดการบริษัท', type: 'link' },
{ path: '/myjob/member-manage', title: 'จัดการผู้สมัครงาน', type: 'link' }
],
},
{
icon: 'buildings',
path: '/myjob/company-departments',
title: 'ทะเบียนบริษัท',
type: 'sub',
children: [
{ path: '/myjob/career-cluster', title: 'จัดการกลุ่มอาชีพ', type: 'link' },
{ path: '/myjob/position', title: 'จัดการตำแหน่ง', type: 'link' },
{ path: '/myjob/job-types', title: 'จัดการประเภทงาน', type: 'link' },
{ path: '/myjob/category-company', title: 'จัดการประเภทธุรกิจ', type: 'link' },
{ path: '/myjob/degree-manage', title: 'จัดการระดับการศึกษา', type: 'link' },
{ path: '/myjob/country-registration', title: 'จัดการประเทศ', type: 'link' },
{ path: '/myjob/provinces', title: 'จัดการจังหวัด', type: 'link' },
],
}
];
}
items = new BehaviorSubject<Menu[]>(this.MENUITEMS); items = new BehaviorSubject<Menu[]>(this.MENUITEMS);
} }
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