Commit aa8d5361 by Natthaphat

เพิ่ม ตอนบันทึก email password ไป register

parent e0c7aed6
...@@ -112,7 +112,8 @@ ...@@ -112,7 +112,8 @@
<td> <span <td> <span
class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span> class="badge bg-{{ item.status == 1 ? 'primary' : 'danger'}} text-white">{{item.getStatus()}}</span>
</td> </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><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>
<td> <td>
...@@ -310,7 +311,8 @@ ...@@ -310,7 +311,8 @@
<div class="text-danger" *ngIf="selectModel.email && (!selectModel.email.includes('@'))"> <div class="text-danger" *ngIf="selectModel.email && (!selectModel.email.includes('@'))">
{{ 'Invalid email format @' | translate }} {{ 'Invalid email format @' | translate }}
</div> </div>
<div class="text-danger" *ngIf="selectModel.email && selectModel.email.includes('@') && !selectModel.email.split('@')[1]?.includes('.')"> <div class="text-danger"
*ngIf="selectModel.email && selectModel.email.includes('@') && !selectModel.email.split('@')[1]?.includes('.')">
{{ 'Invalid email format .' | translate }} {{ 'Invalid email format .' | translate }}
</div> </div>
<div class="text-danger" *ngIf="isEmailDuplicate && action !== 'edit'"> <div class="text-danger" *ngIf="isEmailDuplicate && action !== 'edit'">
...@@ -320,12 +322,11 @@ ...@@ -320,12 +322,11 @@
<div class="xl:col-span-6 col-span-12"> <div class="xl:col-span-6 col-span-12" *ngIf="action !== 'edit'">
<label for="deal-title" class="form-label">{{'Password' | translate}}</label> <label for="password" class="form-label">{{'Password' | translate}}</label>
<input type="password" class="form-control" id="deal-title" placeholder="" [disabled]="action === 'edit'" <input type="text" class="form-control" id="password" placeholder="" [(ngModel)]="password">
[(ngModel)]="selectModel.password"> <div class="text-danger" *ngIf="!password">
<div class="text-danger" *ngIf="!selectModel.password && action !=='edit'"> {{ 'Please fill in information' | translate }}
{{'Please fill in information' | translate}}
</div> </div>
</div> </div>
...@@ -346,7 +347,6 @@ ...@@ -346,7 +347,6 @@
<ng-option [value]="1">{{'Active' | translate}}</ng-option> <ng-option [value]="1">{{'Active' | translate}}</ng-option>
</ng-select> </ng-select>
</div> </div>
</div> </div>
</div> </div>
<div class="ti-modal-footer"> <div class="ti-modal-footer">
...@@ -354,24 +354,22 @@ ...@@ -354,24 +354,22 @@
data-hs-overlay="#modal-detail"> data-hs-overlay="#modal-detail">
{{'Cancel' | translate}} {{'Cancel' | translate}}
</button> </button>
<button type="button" *ngIf="modalStatus=='add'" (click)="save()" class="ti-btn bg-primary text-white !font-medium" <button type="button" *ngIf="modalStatus=='add'" (click)="save()"
class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]=" [class.ti-btn-disabled]="
!selectModel.candidateId ||
!selectModel.thFirstname || !selectModel.thFirstname ||
!selectModel.thLastname || !selectModel.thLastname ||
!selectModel.engFirstname || !selectModel.engFirstname ||
!selectModel.engLastname || !selectModel.engLastname ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) || (!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) ||
!selectModel.password !password
" [disabled]=" " [disabled]="
!selectModel.candidateId ||
!selectModel.thFirstname || !selectModel.thFirstname ||
!selectModel.thLastname || !selectModel.thLastname ||
!selectModel.engFirstname || !selectModel.engFirstname ||
!selectModel.engLastname || !selectModel.engLastname ||
(!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) || (!selectModel.email || isEmailDuplicate || !selectModel.email.includes('@') || !selectModel.email.includes('.')) ||
!selectModel.password !password">
">
{{ 'Save' | translate }} {{ 'Save' | translate }}
</button> </button>
</div> </div>
......
...@@ -4,15 +4,16 @@ import { NgSelectModule } from "@ng-select/ng-select"; ...@@ -4,15 +4,16 @@ import { NgSelectModule } from "@ng-select/ng-select";
import { TranslateModule, TranslateService } from "@ngx-translate/core"; import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { SharedModule } from "../../../../shared/shared.module"; import { SharedModule } from "../../../../shared/shared.module";
import { UserService } from "../../../services/user.service"; import { UserService } from "../../../services/user.service";
import { UserProfileModel } from "../../../models/user.model";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import swal from 'sweetalert'; import swal from 'sweetalert';
import { MatPaginator, PageEvent } from "@angular/material/paginator"; import { MatPaginator, PageEvent } from "@angular/material/paginator";
import { UserRoleModel } from "../../../models/user-role-model";
import { FileUploadModule } from 'ng2-file-upload'; import { FileUploadModule } from 'ng2-file-upload';
import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload"; import { FileItem, FileUploader, ParsedResponseHeaders } from "ng2-file-upload";
import { environment } from "../../../../../environments/environment"; import { environment } from "../../../../../environments/environment";
import { TokenService } from "../../../../shared/services/token.service"; 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({ @Component({
selector: 'app-user-setting', selector: 'app-user-setting',
...@@ -36,19 +37,20 @@ export class UserSettingComponent { ...@@ -36,19 +37,20 @@ export class UserSettingComponent {
allSelected = false; allSelected = false;
someSelected = false; someSelected = false;
confirmPassword = "" confirmPassword = ""
itemsList: UserProfileModel[] = [] itemsList: ProfileModel[] = []
filterList: UserProfileModel[] = [] filterList: ProfileModel[] = []
selectModel: UserProfileModel = new UserProfileModel() selectModel: ProfileModel = new ProfileModel()
selectedItems = new Map<string, boolean>(); selectedItems = new Map<string, boolean>();
roleList: UserRoleModel[] = [] roleList: RoleModel[] = []
empList: UserProfileModel[] = [] empList: ProfileModel[] = []
descName = 'engName' descName = 'engName'
pageIndex = 0; pageIndex = 0;
uploaderProfile: FileUploader | undefined; uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = ""; uploadErrorMsg: string = "";
modalStatus: "add" | "edit" = "add" modalStatus: "add" | "edit" = "add"
existingEmails: UserProfileModel[] = [] existingEmails: ProfileModel[] = []
isEmailDuplicate = false; isEmailDuplicate = false;
password: string = '';
get searchTerm(): string { get searchTerm(): string {
return this._searchTerm; return this._searchTerm;
} }
...@@ -122,7 +124,7 @@ export class UserSettingComponent { ...@@ -122,7 +124,7 @@ export class UserSettingComponent {
ngOnInit(): void { ngOnInit(): void {
this.userService.getListsProfile().subscribe(result => { this.userService.getListsProfile().subscribe(result => {
this.itemsList = result.map(item => new UserProfileModel(item, this.translate)); this.itemsList = result.map(item => new ProfileModel(item, this.translate));
this.filterList = [...this.itemsList]; this.filterList = [...this.itemsList];
this.existingEmails = result; this.existingEmails = result;
}); });
...@@ -136,20 +138,20 @@ export class UserSettingComponent { ...@@ -136,20 +138,20 @@ export class UserSettingComponent {
); );
} }
filter(v: string): UserProfileModel[] { filter(v: string): ProfileModel[] {
const search = v.toLowerCase(); const search = v.toLowerCase();
return this.itemsList?.filter(x => return this.itemsList?.filter(x =>
x.candidateId?.toLowerCase().includes(search) || x.candidateId?.toLowerCase().includes(search) ||
x.username?.toLowerCase().includes(search) ||
x.email?.toLowerCase().includes(search) || x.email?.toLowerCase().includes(search) ||
x.phoneNumberProfile?.toLowerCase().includes(search) || x.email?.toLowerCase().includes(search) ||
x.getStatus?.()?.toLowerCase().includes(search) || x.phoneCurrent?.toLowerCase().includes(search) ||
x.getStatus()?.toLowerCase().includes(search) ||
x.getName?.()?.toLowerCase().includes(search) x.getName?.()?.toLowerCase().includes(search)
); );
} }
delete(item: UserProfileModel) { delete(item: ProfileModel) {
swal({ swal({
title: "Are you sure?", title: "Are you sure?",
text: "You won't be able to revert this!", text: "You won't be able to revert this!",
...@@ -160,7 +162,7 @@ export class UserSettingComponent { ...@@ -160,7 +162,7 @@ export class UserSettingComponent {
}) })
.then((willDelete: any) => { .then((willDelete: any) => {
if (willDelete) { if (willDelete) {
this.userService.delete(item).subscribe(result => { this.userService.put(item).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success"); swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit() this.ngOnInit()
}) })
...@@ -171,14 +173,14 @@ export class UserSettingComponent { ...@@ -171,14 +173,14 @@ export class UserSettingComponent {
new() { new() {
this.action = 'add' this.action = 'add'
this.selectModel = new UserProfileModel() this.selectModel = new ProfileModel()
this.selectModel.status = 1; this.selectModel.status = 1;
} }
view(item: UserProfileModel) { view(item: ProfileModel) {
this.action = 'edit' this.action = 'edit'
this.confirmPassword = '' this.confirmPassword = ''
this.selectModel = new UserProfileModel(item) this.selectModel = new ProfileModel(item)
} }
...@@ -189,34 +191,65 @@ export class UserSettingComponent { ...@@ -189,34 +191,65 @@ export class UserSettingComponent {
icon: "warning", icon: "warning",
dangerMode: false, dangerMode: false,
buttons: ["Cancel", "Confirm"], buttons: ["Cancel", "Confirm"],
}) }).then((willSave: any) => {
.then((willDelete: any) => { if (willSave) {
if (willDelete) { if (this.action === 'add') {
if (this.action == 'add') {
this.userService.save(this.selectModel).subscribe(result => { const body = new AuthModel();
if (this.selectModel.email) { body.username = this.selectModel.email;
swal("Save Success!!", "อีเมลซ่ำ", "warning"); 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");
} }
console.log(result) },
swal("Save Success!!", "บันทึกข้อมูลสมาชิก", "success"); error: err => {
this.ngOnInit() console.error('Error response:', err);
this.childModal?.nativeElement.click() const errorMessage = err?.error?.message || err?.message || 'ไม่ทราบสาเหตุ';
}) if (errorMessage.includes('email')) {
} else if (this.action == 'edit') { swal("Save Failed", "อีเมลซ้ำหรือไม่ถูกต้อง", "warning");
this.userService.update(this.selectModel).subscribe(result => { } else {
console.log(result) swal("Error", errorMessage, "error");
swal("Update Success!!", "บันทึกข้อมูลสมาชิก", "success"); }
this.ngOnInit() }
this.childModal?.nativeElement.click() });
})
}
} 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() { updatePagedItems() {
const startIndex = this.pageIndex * 10; const startIndex = this.pageIndex * 10;
...@@ -228,16 +261,16 @@ export class UserSettingComponent { ...@@ -228,16 +261,16 @@ export class UserSettingComponent {
this.allSelected = event.target.checked; this.allSelected = event.target.checked;
this.selectedItems.clear(); this.selectedItems.clear();
this.itemsList.forEach(item => { this.itemsList.forEach(item => {
this.selectedItems.set(item.candidateId, this.allSelected); this.selectedItems.set(item.candidateId ?? '', this.allSelected);
}); });
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId)); this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId ?? ''));
} }
onCheckboxChange(candidateId: string) { onCheckboxChange(candidateId: string) {
const isSelected = this.selectedItems.get(candidateId) || false; const isSelected = this.selectedItems.get(candidateId) || false;
this.selectedItems.set(candidateId, !isSelected); this.selectedItems.set(candidateId, !isSelected);
this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.candidateId)); this.allSelected = this.itemsList.every(item => this.selectedItems.get(item.candidateId ?? ''));
this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId)); this.someSelected = this.itemsList.some(item => this.selectedItems.get(item.candidateId ?? ''));
} }
deleteSelect() { deleteSelect() {
...@@ -264,7 +297,7 @@ export class UserSettingComponent { ...@@ -264,7 +297,7 @@ export class UserSettingComponent {
if (isSelected) { if (isSelected) {
const user = this.itemsList.find(user => user.candidateId === candidateId); const user = this.itemsList.find(user => user.candidateId === candidateId);
if (user) { if (user) {
this.userService.delete(user).subscribe(result => { this.userService.put(user).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success"); swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit(); this.ngOnInit();
}); });
......
...@@ -427,8 +427,13 @@ export class ProfileModel extends BaseModel implements ProfileModel { ...@@ -427,8 +427,13 @@ export class ProfileModel extends BaseModel implements ProfileModel {
} }
getPicture() { getPicture(): string {
return this.picture ? (environment.baseUrl + "/files/image/" + this.picture) : null if (this.picture) {
return environment.baseUrl + "/files/image/" + this.picture;
} else {
// รูป default ใน assets ต้องใช้ path แบบ relative สำหรับ Angular
return "assets/images/faces/1.jpg";
}
} }
getName() { getName() {
...@@ -485,6 +490,14 @@ export class ProfileModel extends BaseModel implements ProfileModel { ...@@ -485,6 +490,14 @@ export class ProfileModel extends BaseModel implements ProfileModel {
return baseGetName(this.thFullName, this.engFullName, this.translateService.currentLang) return baseGetName(this.thFullName, this.engFullName, this.translateService.currentLang)
} }
getStatus(): string {
if (this.status == 1) {
return this.translateService.instant('Active');
} else {
return this.translateService.instant('Unactive');
}
}
} }
......
...@@ -2,11 +2,11 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; ...@@ -2,11 +2,11 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { TokenService } from '../../shared/services/token.service'; import { TokenService } from '../../shared/services/token.service';
import { UserProfileModel } from '../models/user.model';
import { map, tap, switchMap, filter, reduce } from "rxjs/operators"; import { map, tap, switchMap, filter, reduce } from "rxjs/operators";
import { PageResponseModel, ResponseModel } from '../models/base.model'; import { PageResponseModel, ResponseModel } from '../models/base.model';
import { forkJoin, Observable } from 'rxjs'; import { forkJoin, Observable } from 'rxjs';
import { AuthModel } from '../models/auth.model'; import { AuthModel } from '../models/auth.model';
import { ProfileModel } from '../models/profile.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
...@@ -21,36 +21,36 @@ export class UserService { ...@@ -21,36 +21,36 @@ export class UserService {
getById(id: Number) { getById(id: Number) {
return this.http return this.http
.get<UserProfileModel>(this.apiBaseUrl + "/" + id) .get<ProfileModel>(this.apiBaseUrl + "/" + id)
.pipe(map((e) => new UserProfileModel(e, this.translateService))); .pipe(map((e) => new ProfileModel(e, this.translateService)));
} }
getByUsername(username: string) { getByUsername(username: string) {
return this.http return this.http
.get<UserProfileModel>(this.apiBaseUrl + "/username/" + username) .get<ProfileModel>(this.apiBaseUrl + "/username/" + username)
} }
getLists() { getLists() {
return this.http return this.http
.get<UserProfileModel[]>(this.apiBaseUrl) .get<ProfileModel[]>(this.apiBaseUrl)
.pipe( .pipe(
map((e) => e.map((e) => new UserProfileModel(e, this.translateService))) map((e) => e.map((e) => new ProfileModel(e, this.translateService)))
); );
} }
getListsProfile() { getListsProfile() {
return this.http return this.http
.get<UserProfileModel[]>(this.apiBaseUrl + '/manage-profile/lists') .get<ProfileModel[]>(this.apiBaseUrl + '/manage-profile/lists?status=1')
// .pipe( // .pipe(
// map((e) => e.map((e) => new UserProfileModel(e, this.translateService))) // map((e) => e.map((e) => new ProfileModel(e, this.translateService)))
// ); // );
} }
getListByPageSize(body: { page: number; size: number }) { getListByPageSize(body: { page: number; size: number }) {
return this.http return this.http
.get<PageResponseModel<UserProfileModel>>(this.apiBaseUrl, { .get<PageResponseModel<ProfileModel>>(this.apiBaseUrl, {
params: body, params: body,
}) })
.pipe( .pipe(
...@@ -58,16 +58,16 @@ export class UserService { ...@@ -58,16 +58,16 @@ export class UserService {
return { return {
...page, ...page,
content: page.content.map( content: page.content.map(
(e) => new UserProfileModel(e, this.translateService) (e) => new ProfileModel(e, this.translateService)
), ),
}; };
}) })
); );
} }
getListAllPageSize(): Observable<UserProfileModel[]> { getListAllPageSize(): Observable<ProfileModel[]> {
return this.http return this.http
.get<PageResponseModel<UserProfileModel>>(this.apiBaseUrl, { .get<PageResponseModel<ProfileModel>>(this.apiBaseUrl, {
params: { page: 0, size: 1 }, params: { page: 0, size: 1 },
}) })
.pipe( .pipe(
...@@ -76,7 +76,7 @@ export class UserService { ...@@ -76,7 +76,7 @@ export class UserService {
const size = 500; const size = 500;
const numOfPages = checkData.totalElements / size; const numOfPages = checkData.totalElements / size;
const parallelList: Observable<PageResponseModel<UserProfileModel>>[] = []; const parallelList: Observable<PageResponseModel<ProfileModel>>[] = [];
for (let page = 0; page < numOfPages; page++) { for (let page = 0; page < numOfPages; page++) {
parallelList.push( parallelList.push(
...@@ -88,7 +88,7 @@ export class UserService { ...@@ -88,7 +88,7 @@ export class UserService {
} }
return forkJoin(parallelList).pipe( return forkJoin(parallelList).pipe(
map((response) => { map((response) => {
let data: UserProfileModel[] = []; let data: ProfileModel[] = [];
for (let i = 0; i < response.length; i++) { for (let i = 0; i < response.length; i++) {
data = data.concat(response[i].content); data = data.concat(response[i].content);
} }
...@@ -102,16 +102,16 @@ export class UserService { ...@@ -102,16 +102,16 @@ export class UserService {
); );
} }
register(authModel: AuthModel) { register(body: AuthModel) {
return this.http.post<ResponseModel>(this.apiAuthUrl + '/register', authModel); return this.http.post<ResponseModel>(this.apiAuthUrl + "/register", body);
} }
save(body: UserProfileModel) { save(body: ProfileModel) {
return this.http.post<ResponseModel>(this.apiBaseUrl + '/manage-profile', new UserProfileModel(body)); return this.http.post<ResponseModel>(this.apiBaseUrl + '/manage-profile', new ProfileModel(body));
} }
update(body: UserProfileModel) { update(body: ProfileModel) {
return this.http.post<ResponseModel>(this.apiBaseUrl + "/manage-profile", new UserProfileModel(body)); return this.http.post<ResponseModel>(this.apiBaseUrl + "/manage-profile", new ProfileModel(body));
} }
...@@ -132,12 +132,17 @@ export class UserService { ...@@ -132,12 +132,17 @@ export class UserService {
delete(body: UserProfileModel) { put(body: ProfileModel) {
return this.http.put<ResponseModel>(this.apiBaseUrl + "/manage-profile", new ProfileModel(body));
}
delete(body: ProfileModel) {
const options = { const options = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }), headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
body: new UserProfileModel(body) // ส่งข้อมูลใน body body: new ProfileModel(body) // ส่งข้อมูลใน body
}; };
return this.http.delete<ResponseModel>(this.apiBaseUrl + "/manage-profile", options); return this.http.delete<ResponseModel>(this.apiBaseUrl + "/manage-profile", options);
} }
} }
...@@ -133,7 +133,7 @@ export class NavService implements OnDestroy { ...@@ -133,7 +133,7 @@ export class NavService implements OnDestroy {
}, },
{ headTitle: 'MyPortal' }, { headTitle: 'MyPortal' },
{ {
icon: 'receipt', icon: 'news bx-flip-horizontal',
path: '/admin/portal-category-list', path: '/admin/portal-category-list',
title: 'รายการเอกสาร', title: 'รายการเอกสาร',
type: 'link', type: 'link',
...@@ -155,7 +155,7 @@ export class NavService implements OnDestroy { ...@@ -155,7 +155,7 @@ export class NavService implements OnDestroy {
], ],
}, },
{ {
icon: 'user', icon: 'slider',
path: '/admin/set-excel-reports', path: '/admin/set-excel-reports',
title: 'ตั้งรายงานเอ็กเซล', title: 'ตั้งรายงานเอ็กเซล',
type: 'sub', type: 'sub',
......
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