Commit c5f2b417 by Natthaphat

หน้าจัดการสมาชิก

parent 9f29edbd
......@@ -10,8 +10,9 @@
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' |
<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>
......@@ -56,11 +57,11 @@
<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">{{ '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">{{ 'Mobile' | translate}}</th>
<th scope="col" class="text-start">{{ 'User Group' | 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>
......@@ -70,20 +71,19 @@
@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 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">
<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>
{{item.candidateId}}</a></p>
<!-- <p class="text-[0.75rem] text-muted mb-0">{{item.memberId}}</p> -->
</div>
</div>
</td>
......@@ -98,7 +98,7 @@
</div>
</div>
</td> -->
<td> {{item.firstName}} {{item.lastName}}</td>
<td> {{item.getFullname()}}</td>
<td>
<div>
<span class="block mb-1"><i
......@@ -108,22 +108,22 @@
<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>
class="ri-phone-line me-2 align-middle text-[.875rem] text-[#8c9097] dark:text-white/50 inline-flex"></i>{{item.phoneNumberProfile}}</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.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.updatedAt | date : 'medium'}}</span></td>
<td><span class="badge bg-info/10 text-primary"><i class="bi bi-clock me-1"></i>{{item.lastModifiedDate | 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"
<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)"
......@@ -189,9 +189,10 @@
<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 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>
......@@ -206,7 +207,8 @@
<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">
<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>
......@@ -214,14 +216,15 @@
</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">
<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">
<!-- <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">
......@@ -239,20 +242,53 @@
<div class="text-danger" *ngIf="confirmPassword && (confirmPassword != selectModel.password)">
{{'Password Not Match' | translate}}
</div>
</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">
<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)]="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">{{'นามสกุล(ไทย)' | 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">{{'ชื่อ(อังกฤษ)' | 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">{{'นามสกุล(อังกฤษ)' | 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">{{'ชื่อ-นามสกุล(ไทย)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.thFullName">
<div class="text-danger" *ngIf="!selectModel.thFullName">
{{'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">
<div class="xl:col-span-6 col-span-12" *ngIf="modalStatus=='edit'">
<label for="deal-title" class="form-label">{{'ชื่อ-นามสกุล(อังกฤษ)' | translate}}</label>
<input type="text" class="form-control" id="deal-title" placeholder="" [(ngModel)]="selectModel.engFullName">
<div class="text-danger" *ngIf="!selectModel.engFullName">
{{'Please fill in information' | translate}}
</div>
</div>
......@@ -269,21 +305,21 @@
<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">
[(ngModel)]="selectModel.phoneNumberProfile">
<div class="text-danger" *ngIf="!selectModel.phoneNumberProfile">
{{'Please fill in information' | translate}}
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<!-- <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> -->
<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=""
......
......@@ -46,6 +46,7 @@ export class UserSettingComponent {
pageIndex = 0;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add"
get searchTerm(): string {
return this._searchTerm;
}
......@@ -119,24 +120,25 @@ export class UserSettingComponent {
ngOnInit(): void {
this.userService.getListsProfile().subscribe(result => {
this.itemsList = result
this.updatePagedItems()
})
this.itemsList = result.map(item => new UserProfileModel(item, this.translate));
this.filterList = [...this.itemsList];
});
}
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
filter(v: string): UserProfileModel[] {
const search = v.toLowerCase();
return this.itemsList?.filter(x =>
x.candidateId?.toLowerCase().includes(search) ||
x.username?.toLowerCase().includes(search) ||
x.email?.toLowerCase().includes(search) ||
x.phoneNumberProfile?.toLowerCase().includes(search) ||
x.getStatus?.()?.toLowerCase().includes(search) ||
x.getName?.()?.toLowerCase().includes(search)
);
}
delete(item: UserProfileModel) {
swal({
title: "Are you sure?",
......@@ -166,7 +168,6 @@ export class UserSettingComponent {
this.action = 'edit'
this.confirmPassword = ''
this.selectModel = new UserProfileModel(item)
console.log(this.selectModel)
}
......@@ -213,23 +214,23 @@ export class UserSettingComponent {
this.allSelected = event.target.checked;
this.selectedItems.clear();
this.itemsList.forEach(item => {
this.selectedItems.set(item.memberId, this.allSelected);
this.selectedItems.set(item.candidateId, this.allSelected);
});
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.memberId));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId));
}
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));
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, memberId) => {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
......@@ -245,9 +246,9 @@ export class UserSettingComponent {
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, memberId) => {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
this.userService.delete(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
......@@ -263,9 +264,9 @@ export class UserSettingComponent {
adjustSelect(status: number) {
let title = "Are you sure?"
let employeeInfo = ''; // ตัวแปรสำหรับเก็บข้อมูลพนักงาน
this.selectedItems.forEach((isSelected, memberId) => {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
employeeInfo += `${this.translate.instant('Fullname')}: ${user.getFullname()}\n`;
}
......@@ -280,9 +281,9 @@ export class UserSettingComponent {
})
.then((willDelete: any) => {
if (willDelete) {
this.selectedItems.forEach((isSelected, memberId) => {
this.selectedItems.forEach((isSelected, candidateId) => {
if (isSelected) {
const user = this.itemsList.find(user => user.memberId === memberId);
const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) {
user.status = status
this.userService.update(user).subscribe(result => {
......@@ -298,7 +299,7 @@ export class UserSettingComponent {
}
filterEmp(empId: string) {
this.selectModel = this.empList.filter(e => e.memberId == empId)[0]
this.selectModel = this.empList.filter(e => e.candidateId == empId)[0]
}
}
......@@ -3,6 +3,7 @@ import { BaseModel } from "./base.model";
import { environment } from "../../../environments/environment";
export class UserProfileModel extends BaseModel {
candidateId: string;
memberId: string;
username: string;
password: string;
......@@ -15,48 +16,97 @@ export class UserProfileModel extends BaseModel {
picture: any;
createdAt: string;
updatedAt: string;
thFirstname: string;
thLastname: string;
thFullName: string;
engFirstname: string;
engLastname: string;
engFullName: string;
phoneCurrent: string;
phoneEmergency: string;
phoneGeneral: string;
phoneHome: string;
lastModifiedDate: string;
constructor(
data?: Partial<UserProfileModel>,
translateService?: TranslateService
) {
super(data, translateService);
this.candidateId = data?.candidateId!;
this.memberId = data?.memberId!;
this.username = data?.username!
this.password = data?.password!
this.phoneNumber = data?.phoneNumber || ""
this.firstName = data?.firstName || ""
this.lastName = data?.lastName || ""
this.status = data?.status!
this.email = data?.email!
this.role = data?.role!
this.createdAt = data?.createdAt!
this.updatedAt = data?.updatedAt!
this.username = data?.username!;
this.password = data?.password!;
this.phoneNumber = data?.phoneNumber || "";
this.firstName = data?.firstName || "";
this.lastName = data?.lastName || "";
this.status = data?.status!;
this.email = data?.email!;
this.role = data?.role!;
this.createdAt = data?.createdAt!;
this.updatedAt = data?.updatedAt!;
this.thFirstname = data?.thFirstname!;
this.thLastname = data?.thLastname!;
this.thFullName = data?.thFullName!;
this.engFirstname = data?.engFirstname!;
this.engLastname = data?.engLastname!;
this.engFullName = data?.engFullName!;
this.phoneCurrent = data?.phoneCurrent || "";
this.phoneEmergency = data?.phoneEmergency || "";
this.phoneGeneral = data?.phoneGeneral || "";
this.phoneHome = data?.phoneHome || "";
this.lastModifiedDate = data?.lastModifiedDate || "";
}
// Getter/Setter สำหรับ phoneNumberProfile (fallback เบอร์โทร)
get phoneNumberProfile(): string {
return this.phoneCurrent || this.phoneEmergency || this.phoneGeneral || this.phoneHome || "";
}
set phoneNumberProfile(value: string) {
if (!this.phoneCurrent && !this.phoneEmergency && !this.phoneGeneral && !this.phoneHome) {
this.phoneCurrent = value;
} else if (this.phoneCurrent) {
this.phoneCurrent = value;
} else if (this.phoneEmergency) {
this.phoneEmergency = value;
} else if (this.phoneGeneral) {
this.phoneGeneral = value;
} else {
this.phoneHome = value;
}
}
getRole(): string {
if (this.role == 99) {
return this.translateService.instant('Admin-System')
}
else if (this.role == 1) {
return this.translateService.instant('Admin-Company')
return this.translateService.instant('Admin-System');
} else if (this.role == 1) {
return this.translateService.instant('Admin-Company');
} else {
return this.translateService.instant('User')
return this.translateService.instant('User');
}
}
getStatus(): string {
if (this.status == 1) {
return this.translateService.instant('Active')
return this.translateService.instant('Active');
} else {
return this.translateService.instant('Unactive')
return this.translateService.instant('Unactive');
}
}
getPicture(): string {
return this.picture ? environment.baseUrl + '/images/' + this.picture : './assets/images/faces/1.jpg'
return this.picture ? environment.baseUrl + '/images/' + this.picture : './assets/images/faces/1.jpg';
}
getFullname(): string {
return this.firstName + " " + this.lastName
return this.thFirstname + " " + this.thLastname;
}
getName(): string {
const th = this.thFullName || '';
const en = this.engFullName || '';
return this.translateService?.currentLang === 'th' ? th : en;
}
}
......@@ -39,7 +39,7 @@ export class UserService {
getListsProfile() {
return this.http
.get<UserProfileModel[]>(this.apiBaseUrl+'/manage-profile/lists')
.get<UserProfileModel[]>(this.apiBaseUrl + '/manage-profile/lists')
// .pipe(
// map((e) => e.map((e) => new UserProfileModel(e, this.translateService)))
// );
......@@ -101,11 +101,11 @@ export class UserService {
}
save(body: UserProfileModel) {
return this.http.post<ResponseModel>(this.apiBaseUrl, new UserProfileModel(body));
return this.http.post<ResponseModel>(this.apiBaseUrl + '/manage-profile', new UserProfileModel(body));
}
update(body: UserProfileModel) {
return this.http.put<ResponseModel>(this.apiBaseUrl + "/" + body.memberId, new UserProfileModel(body));
return this.http.put<ResponseModel>(this.apiBaseUrl + "/" + body.candidateId, new UserProfileModel(body));
}
......@@ -128,11 +128,10 @@ export class UserService {
delete(body: UserProfileModel) {
const options = {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
body: new UserProfileModel(body),
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
body: new UserProfileModel(body) // ส่งข้อมูลใน body
};
return this.http.delete<ResponseModel>(this.apiBaseUrl + "/" + body.memberId);
return this.http.delete<ResponseModel>(this.apiBaseUrl + "/manage-profile", options);
}
}
......@@ -9911,6 +9911,13 @@ span.flatpickr-weekday {
@apply text-white;
}
.bg-input-readonly {
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
}
.\!bg-input-readonly {
background-color: rgb(241 245 249) !important;
}
[dir=rtl] pre[class*=language-] > code {
@apply border-l-0 text-right !important;
}
......
......@@ -2,6 +2,7 @@
"Home": "Home",
"All List": "All List",
"Create": "Create",
"Edit": "Edit",
"Delete": "Delete",
"Search": "Search",
"Close": "Close",
......@@ -73,5 +74,6 @@
"Success": "Success",
"Time": "Time",
"Fail": "Fail",
"Mobile": "Mobile"
"Mobile": "Mobile",
"Candidate ID": "Candidate ID"
}
......@@ -2,6 +2,7 @@
"Home": "หน้าแรก",
"All List": "รายการทั้งหมด",
"Create": "สร้าง",
"Edit": "แก้ไข",
"Delete": "ลบ",
"Search": "ค้นหา",
"Close": "ปิด",
......@@ -73,5 +74,6 @@
"Browser" : "เบราว์เซอร์",
"Success" : "สำเร็จ",
"Fail" : "ผิดพลาด",
"Mobile" : "เบอร์ติดต่อ"
"Mobile" : "เบอร์ติดต่อ",
"Candidate ID": "รหัสสมาชิก"
}
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