Commit 4ee746ce by DESKTOP-E0VCCBD\zedan

update

parent 0d0c4672
......@@ -46,10 +46,8 @@ export class AdminProjectEquirementComponent {
uploadErrorMsg: string = "";
itemsList: ProjectEquipmentModel[] = []
filterList: ProjectEquipmentModel[] = []
itemsListAll: EquipmentModel[] = []
filterListAll: EquipmentModel[] = []
selectModel: ProjectEquipmentModel = new ProjectEquipmentModel()
selectStock?: EquipmentStockModel
selectedItems = new Map<string, boolean>();
......
......@@ -44,10 +44,8 @@ export class EmpBorrowManageComponent {
uploadErrorMsg: string = "";
itemsList: ProjectEquipmentModel[] = []
filterList: ProjectEquipmentModel[] = []
itemsListAll: EquipmentModel[] = []
filterListAll: EquipmentModel[] = []
selectModel: ProjectEquipmentModel = new ProjectEquipmentModel()
selectStock?: EquipmentStockModel
selectedItems = new Map<string, boolean>();
......
<p>
emp-borrow-return-status works!
</p>
<app-page-header
[title]="'อนุมัตการคืนอุปกรณ์'"
[activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'อนุมัตการคืนอุปกรณ์'"
></app-page-header>
<div class="grid grid-cols-12 gap-x-6">
<div class="xl:col-span-12 col-span-12">
<div class="box mt-6">
<div class="box-header justify-between">
<div class="box-title">
{{ "รายการทั้งหมด" | translate }}
<span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle"
>{{ hisList.length }}</span
>
</div>
<!-- แท็บสถานะ -->
<div class="flex flex-wrap gap-2">
<!-- สถานะทั้งหมด -->
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-blue-100 text-blue-800 border-blue-200"
(click)="filterByStatus('all')"
>
ทั้งหมด
</button>
</div>
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-warning/10 text-warning border-warning/20"
(click)="filterByStatus('requested')"
>
รออนุมัติ
</button>
</div>
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-success/10 text-success border-success/20"
(click)="filterByStatus('approved')"
>
อนุมัติแล้ว
</button>
</div>
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-danger/10 text-danger border-danger/20"
(click)="filterByStatus('rejected')"
>
ไม่อนุมันติ
</button>
</div>
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-info/10 text-info border-info/20"
(click)="filterByStatus('returned')"
>
คืนแล้ว
</button>
</div>
</div>
<div class="flex flex-wrap gap-2">
<div>
<input
[(ngModel)]="searchTerm"
class="form-control form-control"
type="text"
placeholder="{{ 'ค้นหารายการ...' | translate }}"
aria-label=".form-control-sm example"
/>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap table-bordered min-w-full">
<thead class="bg-light">
<tr>
<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">สถานะ</th>
<th scope="col" class="text-start">ผู้อนุมัติ</th>
<th scope="col" class="text-start">การดำเนินการ</th>
</tr>
</thead>
<tbody>
@for(product of filteredList; track product.peId){
<tr class="product-list">
<td>
{{ product.project_equipment?.equipment?.equipmentName }}
</td>
<td>
<div class="flex items-center">
<div class="font-semibold">
{{ product.member?.getFullname() }}
</div>
</div>
</td>
<td>{{ product.quantity_borrowed }}</td>
<td>{{ product.created_at | date : "dd/MM/yyyy HH:mm" }}</td>
<td>
@if(product.returned_date) {
{{ product.returned_date | date : "dd/MM/yyyy HH:mm" }}
}
</td>
<td>
<span
class="badge"
[ngClass]="{
'bg-success/10 text-success':
product.status === 'approved',
'bg-warning/10 text-warning':
product.status === 'requested',
'bg-danger/10 text-danger': product.status === 'rejected',
'bg-info/10 text-info': product.status === 'returned',
'bg-purple-100 text-purple-800':
product.status === 'repairing'
}"
>
{{ getStatusText(product.status) }}
</span>
</td>
<td>{{ product.approved_by_member?.getFullname() || "-" }}</td>
<td>
<div class="flex gap-1">
<!-- ปุ่มอนุมัติการคืน -->
@if(product.project_equipment?.equipment?.is_returnable &&
product.status === 'approved' && !product.returned_date) {
<button
aria-label="อนุมัติการคืน"
(click)="view(product)"
class="ti-btn ti-btn-sm ti-btn-success"
data-hs-overlay="#detail-container"
>
<i class="ri-check-line"></i>
</button>
}
<!-- ปุ่มแจ้งซ่อม -->
@if(product.project_equipment?.equipment?.is_returnable &&
(product.status === 'approved' || product.status ===
'returned')) {
<button
aria-label="แจ้งซ่อม"
(click)="reportRepair(product)"
class="ti-btn ti-btn-sm ti-btn-warning"
>
<i class="ri-tools-line"></i>
</button>
} @if(product.status === 'approved' || product.status ===
'returned'){
<button
aria-label="รายละเอียด"
(click)="view(product)"
class="ti-btn ti-btn-sm ti-btn-light me-[0.375rem]"
data-hs-overlay="#detail-borrow"
>
<i class="fe fe-eye"></i>
</button>
}
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div
id="detail-container"
class="hs-overlay hidden ti-modal"
*ngIf="selectedBorrowItem as item"
>
<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"
>
รายละเอียดการยืม
</h6>
<button
type="button"
class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#detail-container"
>
<span class="sr-only">Close</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-name" class="form-label">ชื่ออุปกรณ์</label>
<input
readonly
type="text"
class="form-control"
id="deal-name"
placeholder="ชื่ออุปกรณ์"
[ngModel]="
selectedBorrowItem.project_equipment?.equipment?.equipmentName
"
/>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-name" class="form-label">จำนวน</label>
<input
type="number"
class="form-control"
id="quantity"
placeholder="จำนวน"
[(ngModel)]="selectedBorrowItem.quantity_borrowed"
/>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="deal-lead-score" class="form-label">หมายเหตุ</label>
<textarea
class="form-control"
id="job-description"
[(ngModel)]="selectStock.remark"
rows="4"
></textarea>
</div>
</div>
<div class="ti-modal-footer">
<button
#closeModalStock
type="button"
class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#detail-container"
>
ยกเลิก
</button>
<button
type="button"
class="ti-btn bg-primary text-white !font-medium"
data-hs-overlay="#detail-container"
(click)="approve(item)"
>
บันทึก
</button>
</div>
</div>
</div>
</div>
</div>
<!-- ในส่วน template -->
<div id="detail-borrow" class="hs-overlay hidden ti-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">
<h6
class="modal-title text-[1rem] font-semibold text-defaulttextcolor"
>
รายละเอียดการยืม
</h6>
<button
type="button"
class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay="#detail-borrow"
>
<span class="sr-only">Close</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="ti-modal-body px-4" *ngIf="selectedBorrowItem">
<div class="grid grid-cols-12 gap-4">
<!-- ข้อมูลผู้ยืม -->
<div class="xl:col-span-12 col-span-12">
<label class="form-label">ชื่อผู้ยืม</label>
<input
readonly
type="text"
class="form-control"
[(ngModel)]="memberList.member.getFullname"
/>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">เบอร์โทรติดต่อ</label>
<input
readonly
type="text"
class="form-control"
[(ngModel)]="memberList.member.phoneNumber"
/>
</div>
<!-- ข้อมูลอุปกรณ์ -->
<div class="xl:col-span-12 col-span-12">
<label class="form-label">ชื่ออุปกรณ์</label>
<input
readonly
type="text"
class="form-control"
[(ngModel)]="Projecteqlist.equipment.equipmentName"
/>
</div>
<!-- ข้อมูลโปรเจค -->
<div class="xl:col-span-12 col-span-12">
<label class="form-label">โครงการที่ยืม</label>
<input
readonly
type="text"
class="form-control"
[(ngModel)]="projectList.project_name"
/>
</div>
<!-- ข้อมูลการยืม -->
<div class="xl:col-span-6 col-span-12">
<label class="form-label">จำนวนที่ยืม</label>
<input
readonly
type="number"
class="form-control"
[(ngModel)]="selectedBorrowItem.quantity_borrowed"
/>
</div>
<div class="xl:col-span-6 col-span-12">
<label class="form-label">วันที่ยืม</label>
<input
readonly
type="text"
class="form-control"
[(ngModel)]="selectedBorrowItem.created_at"
/>
</div>
</div>
</div>
<div class="ti-modal-footer">
<button
type="button"
class="ti-btn ti-btn-light align-middle"
data-hs-overlay="#detail-borrow"
>
ปิด
</button>
<!-- <button
type="button"
class="ti-btn bg-primary text-white !font-medium"
data-hs-overlay="#detail-borrow"
(click)="approve(item)"
>
บันทึก
</button> -->
</div>
</div>
</div>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { UserModel } from './../../../shared/user-auth.model';
import { ProjectEquipmentService } from './../../services/project-equipments.service';
import { ProjectMemberService } from './../../services/project-members.service';
import { filter } from 'rxjs/operators';
import { CommonModule } from "@angular/common";
import { Component, ViewChild, ElementRef } 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 { SharedModule } from "../../../shared/shared.module";
import { TokenService } from "../../../shared/services/token.service";
import { BorrowTransactionsService } from '../../services/borrow-transactions.service';
import { BorrowTransactionsModel } from '../../models/borrow-transactions';
import { EquipmentService } from "../../services/equirement.service";
import { EquipmentModel, EquipmentStockModel } from "../../models/equipments.model";
import { ProjectEquipmentModel } from "../../models/project-equipments";
import { ProjectMemberModel } from '../../models/project-members';
import { HttpClient } from '@angular/common/http';
import { FileUploader } from 'ng2-file-upload';
import { ProjectModel } from '../../models/project.model';
@Component({
selector: 'app-emp-borrow-return-status',
templateUrl: './emp-borrow-return-status.component.html',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule
],
styleUrls: ['./emp-borrow-return-status.component.scss']
})
export class EmpBorrowReturnStatusComponent implements OnInit {
constructor() { }
export class EmpBorrowReturnStatusComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('closeModalStock') public closeModalStock?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
returnList: BorrowTransactionsModel[] = [];
memberList: UserModel;
Projecteqlist: ProjectEquipmentModel;
projecteMember: ProjectMemberModel;
selectedBorrowItem: BorrowTransactionsModel;
projectList:ProjectModel;
allSelected = false;
someSelected = false;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
itemsList: ProjectEquipmentModel[] = [];
filterList: ProjectEquipmentModel[] = [];
itemsListAll: EquipmentModel[] = [];
filterListAll: EquipmentModel[] = [];
selectModel: ProjectEquipmentModel = new ProjectEquipmentModel()
selectStock: EquipmentStockModel
selectedItems = new Map<string, boolean>();
borrowSelect: BorrowTransactionsModel = new BorrowTransactionsModel()
filteredList: any[] = [];
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()
}
}
projectId = ""
_searchTerm = "";
isEdit = false;
empList: ProjectMemberModel[] = []
hisList: BorrowTransactionsModel [] = [];
selectedStatus: string = 'all';
constructor(
private http: HttpClient,
private eqService: EquipmentService,
public translate: TranslateService,
private tokenService: TokenService,
private projectEquipmentService: ProjectEquipmentService,
private borrowTransactionsService: BorrowTransactionsService,
private projectMemberService: ProjectMemberService) {
this.projectId = this.tokenService.getSelectCompany().projectId!;
}
@ViewChild('video') video: ElementRef;
@ViewChild('canvas') canvas: ElementRef;
capturedImage: string | null = null;
uploadStatus: string = '';
checkMatch = false;
memberId = ""
isFaceDetected = false; // Flag to determine if a face is detected
ngOnInit(): void {
this.loadReturnList();
}
loadReturnList(): void {
this.borrowTransactionsService.getLists().subscribe(result => {
this.hisList = result;
// เรียงลำดับจากวันที่ล่าสุด
this.hisList.sort((a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
);
this.applyFilter();
});
}
filterByStatus(status: string): void {
this.selectedStatus = status;
this.applyFilter();
}
applyFilter(): void {
let filtered = [...this.hisList];
// กรองตามสถานะ
if (this.selectedStatus !== 'all') {
filtered = filtered.filter(item => item.status === this.selectedStatus);
}
// กรองตามคำค้นหา
if (this.searchTerm) {
const term = this.searchTerm.toLowerCase();
filtered = filtered.filter(item =>
(item.project_equipment?.equipment?.equipmentName?.toLowerCase().includes(term)) ||
(item.member?.getFullname()?.toLowerCase().includes(term)) ||
(item.quantity_borrowed?.toString().includes(term))
);
}
this.filteredList = filtered;
ngOnInit() {
}
getUserProject() {
this.projectMemberService.getLists(this.projectId).subscribe(result => {
this.empList = result
})
}
getCompanyEquirment() {
this.eqService.getLists().subscribe(result => {
this.itemsListAll = result.filter(e => e.quantity > 0)
this.updatePagedItemsAll()
})
}
getProjectEquirment() {
this.projectEquipmentService.getLists(this.projectId).subscribe(result => {
this.itemsList = result
this.updatePagedItems()
})
}
filter(v: string) {
this.pageIndex = 0;
return this.itemsList?.filter(
(x) =>
x.equipment.equipmentName.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.equipment.description?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
getfilteredItems() {
return this.returnList.filter(item =>
item.project_equipment?.equipment?.equipmentName.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
item.member?.getFullname().toLowerCase().includes(this.searchTerm.toLowerCase())
);
}
getStatusText(status: string): string {
switch(status) {
case 'requested': return 'รออนุมัติ';
case 'approved': return 'อนุมัติแล้ว';
case 'rejected': return 'ไม่อนุมัติ';
case 'returned': return 'คืนแล้ว';
case 'repairing': return 'กำลังซ่อม';
default: return status;
}
}
viewStock(item: ProjectEquipmentModel) {
this.selectModel = new ProjectEquipmentModel(item)
this.borrowSelect = new BorrowTransactionsModel()
// this.selectStock = new EquipmentStockModel()
// this.selectStock.equipmentId = this.selectModel.equipmentId
// this.selectStock.created_by = this.tokenService.getUser().member.memberId
// this.selectStock.action = "INBOUND"
}
viewHisStock(item: ProjectEquipmentModel) {
this.borrowTransactionsService.search({ "peId": item.peId , "member_id" :this.tokenService.getUser().member.memberId }).subscribe(result => {
this.hisList = result
})
}
view(item: BorrowTransactionsModel) {
console.log('รายการที่เลือก:', item);
this.isEdit = true;
this.selectedBorrowItem = item;
}
openBorrowDetail(item: any) {
this.selectedBorrowItem = item;
setTimeout(() => {
const detailModal = document.querySelector('#detail-borrow') as any;
if (detailModal) {
(window as any).HSOverlay.open(detailModal);
}
});
}
approve(item: BorrowTransactionsModel) {
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
// เตรียมข้อมูลที่จะส่งไป API
let body = {
quantity_borrowed: item.quantity_borrowed, // อาจจะอัพเดทจำนวนยืมที่เหลือ
memberId: item.memberId,
status: "returned", // เปลี่ยนสถานะเป็น "returned"
approved_by: this.tokenService.getUser().member.memberId // ค่าผู้ที่อนุมัติ
};
// ทำการอัพเดทข้อมูลใน API
this.borrowTransactionsService.update(item.borrowId, body).subscribe(
(result) => {
// เมื่อบันทึกสำเร็จ
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// อัพเดทข้อมูลในตัว item ด้วยค่าใหม่ที่ได้รับจาก API (ถ้ามี)
item.status = "returned"; // อัพเดทสถานะ
item.quantity_borrowed = 0; // อัพเดทจำนวนยืม
// เรียก ngOnInit หรือการโหลดข้อมูลใหม่หลังการบันทึก
this.ngOnInit();
},
(error: any) => {
// เมื่อเกิดข้อผิดพลาด
swal("Fail!!", error.error.detail, "info");
}
);
}
});
}
reject(item: BorrowTransactionsModel) {
swal({
title: "ยืนยันการไม่อนุมัติ",
text: "คุณต้องการไม่อนุมัติการยืมนี้หรือไม่?",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ไม่อนุมัติ"],
}).then((willReject) => {
if (willReject) {
let body = {
"quantity_borrowed": item.quantity_borrowed,
"memberId": item.memberId,
"status": "rejected",
"approved_by": this.tokenService.getUser().member.memberId
}
this.borrowTransactionsService.update(item.borrowId, body).subscribe
(result => {
swal("ไม่อนุมัติสำเร็จ", "การยืมอุปกรณ์ถูกปฏิเสธแล้ว", "success");
this.loadReturnList();
},
(error) => {
swal("เกิดข้อผิดพลาด", error.error.detail, "error");
}
);
}
});
}
reportRepair(item: BorrowTransactionsModel): void {
swal({
title: "แจ้งซ่อมอุปกรณ์",
text: `คุณต้องการแจ้งซ่อมอุปกรณ์ ${item.project_equipment?.equipment?.equipmentName} หรือไม่?`,
content: {
element: "input",
attributes: {
placeholder: "ระบุอาการเสีย/ปัญหาที่พบ",
type: "text",
},
},
icon: "warning",
buttons: ["ยกเลิก", "แจ้งซ่อม"],
}).then((repairDescription) => {
if (repairDescription) {
const repairData = {
borrowTransactionId: item.borrowId,
equipmentId: item.project_equipment?.equipment?.equipmentId,
reportedBy: this.tokenService.getUser().member.memberId,
description: repairDescription,
status: 'pending'
};
// อัปเดตสถานะการยืมเป็น repairing
const updateBorrowData = {
status: 'repairing'
};
// // สร้างรายการซ่อม
// this.equipmentRepairService.create(repairData).subscribe(
// (result) => {
// // อัปเดตสถานะการยืม
// this.borrowTransactionsService.update(item.borrowId, updateBorrowData).subscribe(
// (updateResult) => {
// swal("แจ้งซ่อมสำเร็จ", "ระบบได้บันทึกการแจ้งซ่อมแล้ว", "success");
// this.loadReturnList();
// },
// (updateError) => {
// swal("เกิดข้อผิดพลาด", "ไม่สามารถอัปเดตสถานะการยืมได้", "error");
// }
// );
// },
// (result) => {
// swal("เกิดข้อผิดพลาด", "ไม่สามารถแจ้งซ่อมได้", "error");
// }
// );
}
});
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this.filterList = this.itemsList
}
updatePagedItemsAll() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this.filterListAll = this.itemsListAll
}
}
<p>
emp-borrow-status works!
</p>
<app-page-header
[title]="'อนุมัตการยืมอุปกรณ์'"
[activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'อนุมัตการยืมอุปกรณ์'"
></app-page-header>
<div class="grid grid-cols-12 gap-x-6">
<div class="xl:col-span-12 col-span-12">
<div class="box mt-6">
<div class="box-header justify-between">
<div class="box-title">
{{ "รายการทั้งหมด" | translate }}
<span
class="badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle"
>{{ hisList.length }}</span
>
</div>
<!-- แท็บสถานะ -->
<div class="flex flex-wrap gap-2">
<!-- สถานะทั้งหมด -->
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-blue-100 text-blue-800 border-blue-200"
(click)="filterByStatus('all')"
>
ทั้งหมด
</button>
</div>
<!-- สถานะรออนุมัติ -->
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-warning/10 text-warning border-warning/20"
(click)="filterByStatus('requested')"
>
รออนุมัติ
</button>
</div>
<!-- สถานะอนุมัติแล้ว -->
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-success/10 text-success border-success/20"
(click)="filterByStatus('approved')"
>
อนุมัติแล้ว
</button>
</div>
<div>
<button
class="px-4 py-2 rounded-full border text-sm font-medium bg-danger/10 text-danger border-danger/20"
(click)="filterByStatus('rejected')"
>
ไม่อนุมันติ
</button>
</div>
</div>
<div class="flex flex-wrap gap-2">
<div>
<input
[(ngModel)]="searchTerm"
class="form-control form-control"
type="text"
placeholder="{{ 'ค้นหารายการ...' | translate }}"
aria-label=".form-control-sm example"
/>
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive">
<table class="table whitespace-nowrap table-bordered min-w-full">
<thead class="bg-light">
<tr>
<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">สถานะ</th>
<th scope="col" class="text-start">ผู้อนุมัติ</th>
<th scope="col" class="text-start">การดำเนินการ</th>
</tr>
</thead>
<tbody>
@for(product of filteredList;track product.peId){
<tr class="product-list">
<td>
{{ product.project_equipment?.equipment?.equipmentName}}
</td>
<td>
<div class="flex items-center">
<div class="font-semibold">
{{ product.member?.getFullname() }}
</div>
</div>
</td>
<td>{{ product.quantity_borrowed }}</td>
<td>{{ product.created_at | date:'dd/MM/yyyy HH:mm' }}</td>
<td>{{ product.returned_date | date:'dd/MM/yyyy HH:mm' }}</td>
<td>
<span class="badge" [ngClass]="{
'bg-success/10 text-success': product.status === 'approved',
'bg-warning/10 text-warning': product.status === 'requested',
'bg-danger/10 text-danger': product.status === 'rejected',
'bg-info/10 text-info': product.status === 'returned'
}">
{{ getStatusText(product.status) }}
</span>
</td>
<td>{{ product.approved_by_member?.getFullname() || '-' }}</td>
<td>
<button *ngIf="product.status === 'requested'"
aria-label="button"
(click)="approve(product)"
class="ti-btn ti-btn-sm ti-btn-success me-1"
>
<i class="ri-check-line"></i>
</button>
<button *ngIf="product.status === 'requested'"
aria-label="button"
(click)="reject(product)"
class="ti-btn ti-btn-sm ti-btn-danger"
>
<i class="ri-close-line"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { BorrowTransactionsService } from './../../services/borrow-transactions.service';
import { CommonModule } from "@angular/common";
import { 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 { SharedModule } from "../../../shared/shared.module";
import { TokenService } from "../../../shared/services/token.service";
import { BorrowTransactionsModel } from '../../models/borrow-transactions';
import { EquipmentService } from '../../services/equirement.service';
import { ProjectEquipmentService } from '../../services/project-equipments.service';
import { ProjectMemberService } from '../../services/project-members.service';
import { ProjectMemberModel } from '../../models/project-members';
import { HttpClient } from '@angular/common/http';
import { ProjectEquipmentModel } from '../../models/project-equipments';
import { EquipmentModel, EquipmentStockModel } from '../../models/equipments.model';
import { FileUploader } from 'ng2-file-upload';
@Component({
selector: 'app-emp-borrow-status',
standalone: true,
imports: [
CommonModule,
SharedModule,
TranslateModule,
NgSelectModule,
FormsModule
],
templateUrl: './emp-borrow-status.component.html',
styleUrls: ['./emp-borrow-status.component.scss']
})
export class EmpBorrowStatusComponent implements OnInit {
export class EmpBorrowStatusComponent {
@ViewChild('closeModal') public childModal?: ElementRef;
@ViewChild('closeModalStock') public closeModalStock?: ElementRef;
@ViewChild('modalDetail') public modalDetail?: ElementRef;
returnList: BorrowTransactionsModel[] = [];
selectedBorrowItem: BorrowTransactionsModel;
allSelected = false;
someSelected = false;
uploaderProfile: FileUploader | undefined;
uploadErrorMsg: string = "";
itemsList: ProjectEquipmentModel[] = [];
filterList: ProjectEquipmentModel[] = [];
itemsListAll: EquipmentModel[] = [];
filterListAll: EquipmentModel[] = [];
selectModel: ProjectEquipmentModel = new ProjectEquipmentModel()
selectStock: EquipmentStockModel
selectedItems = new Map<string, boolean>();
borrowSelect: BorrowTransactionsModel = new BorrowTransactionsModel()
filteredList: any[] = [];
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()
}
}
projectId = ""
_searchTerm = "";
isEdit = false;
empList: ProjectMemberModel[] = []
hisList: BorrowTransactionsModel [] = [];
selectedStatus: string = 'all';
constructor(
private http: HttpClient,
private eqService: EquipmentService,
public translate: TranslateService,
private tokenService: TokenService,
private projectEquipmentService: ProjectEquipmentService,
private borrowTransactionsService: BorrowTransactionsService,
private projectMemberService: ProjectMemberService) {
this.projectId = this.tokenService.getSelectCompany().projectId!;
}
ngOnInit(): void {
this.loadBorrowHistory();
}
loadBorrowHistory(): void {
this.borrowTransactionsService.getLists().subscribe(result => {
this.hisList = result;
// เรียงลำดับจากวันที่ล่าสุด
this.hisList.sort((a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
);
this.applyFilter();
});
}
getStatusText(status: string): string {
switch(status) {
case 'requested': return 'รออนุมัติ';
case 'approved': return 'อนุมัติแล้ว';
case 'rejected': return 'ไม่อนุมัติ';
case 'returned': return 'คืนแล้ว';
case 'repairing': return 'กำลังซ่อม';
default: return status;
}
}
approve(item : BorrowTransactionsModel){
// console.log(this.selectStock)
swal({
title: "Are you sure?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["Cancel", "Confirm"],
})
.then((willDelete: any) => {
if (willDelete) {
let body = {
"quantity_borrowed": item.quantity_borrowed,
"memberId" : item.memberId,
"status": "approved",
"approved_by": this.tokenService.getUser().member.memberId
}
this.borrowTransactionsService.update(item.borrowId , body).subscribe(result => {
swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
this.ngOnInit()
}, (error: any) => {
swal("Fail!!", error.error.detail, "info");
})
}
});
constructor() { }
ngOnInit() {
}
reject(item: BorrowTransactionsModel) {
swal({
title: "ยืนยันการไม่อนุมัติ",
text: "คุณต้องการไม่อนุมัติการยืมนี้หรือไม่?",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ไม่อนุมัติ"],
}).then((willReject) => {
if (willReject) {
let body = {
"quantity_borrowed": item.quantity_borrowed,
"memberId" : item.memberId,
"status": "rejected",
"approved_by": this.tokenService.getUser().member.memberId
}
this.borrowTransactionsService.update(item.borrowId, body).subscribe
(result => {
swal("ไม่อนุมัติสำเร็จ", "การยืมอุปกรณ์ถูกปฏิเสธแล้ว", "success");
this.loadBorrowHistory();
},
(error) => {
swal("เกิดข้อผิดพลาด", error.error.detail, "error");
}
);
}
});
}
filter(v: string) {
this.pageIndex = 0;
return this.itemsList?.filter(
(x) =>
x.equipment.equipmentName.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.equipment.description?.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
updatePagedItems() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this.filterList = this.itemsList
}
updatePagedItemsAll() {
const startIndex = this.pageIndex * 10;
const endIndex = startIndex + 10;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this.filterListAll = this.itemsListAll
}
filterByStatus(status: string): void {
this.selectedStatus = status;
this.applyFilter();
}
applyFilter(): void {
let filtered = [...this.hisList];
// กรองตามสถานะ
if (this.selectedStatus !== 'all') {
filtered = filtered.filter(item => item.status === this.selectedStatus);
}
// กรองตามคำค้นหา
if (this.searchTerm) {
const term = this.searchTerm.toLowerCase();
filtered = filtered.filter(item =>
(item.project_equipment?.equipment?.equipmentName?.toLowerCase().includes(term)) ||
(item.member?.getFullname()?.toLowerCase().includes(term)) ||
(item.quantity_borrowed?.toString().includes(term))
);
}
this.filteredList = filtered;
}
}
......@@ -5,8 +5,10 @@ import { EquipmentModel } from "./equipments.model";
import { ProjectEquipmentModel } from "./project-equipments";
export class BorrowTransactionsModel extends BaseModel {
peId: string;
quantity_borrowed: number;
eqName:string;
status: string;
returned_date: string;
memberId: string;
......@@ -16,9 +18,11 @@ export class BorrowTransactionsModel extends BaseModel {
member: UserProfileModel;
project_equipment: ProjectEquipmentModel;
approved_by_member: UserProfileModel;
rejected_reason:string;
constructor(data?: Partial<BorrowTransactionsModel>, translateService?: TranslateService) {
super(data, translateService);
this.eqName = data?.eqName ?? '';
this.borrowId = data?.borrowId ?? '';
this.peId = data?.peId ?? '';
this.quantity_borrowed = data?.quantity_borrowed ?? 0;
......@@ -26,6 +30,7 @@ export class BorrowTransactionsModel extends BaseModel {
this.returned_date = data?.returned_date ?? ''
this.memberId = data?.memberId ?? ''
this.approved_by = data?.approved_by ?? ''
this.rejected_reason = data?.rejected_reason ?? ''
this.member = data?.member ? new UserProfileModel(data.member) : new UserProfileModel();
this.approved_by_member = data?.approved_by_member ? new UserProfileModel(data.approved_by_member) : new UserProfileModel();
this.project_equipment = data?.project_equipment ? new ProjectEquipmentModel(data.project_equipment) : new ProjectEquipmentModel();
......
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class EquipmentRepairService {
constructor() { }
}
// equipment-repair.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from '../../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class EquipmentRepairService {
apiBaseUrl = "/equipments";
constructor(
private http: HttpClient
) { }
create(repairData: any) {
return this.http.post<EquipmentRepairModel>(this.apiBaseUrl, repairData);
}
update(id: number, repairData: any) {
return this.http.put(`${this.apiBaseUrl}/${id}`, repairData);
}
getList() {
return this.http.get<EquipmentRepairModel[]>(this.apiBaseUrl);
}
}
<!-- Start::Header -->
<header class="app-header">
<nav class="main-header !h-[3.75rem]" aria-label="Global">
<div class="main-header-container ps-[0.725rem] pe-[1rem] ">
<div class="main-header-container ps-[0.725rem] pe-[1rem]main-header-container ps-[0.725rem] pe-[1rem] bg-neutral-600 text-white ">
<div class="header-content-left">
<!-- Start::header-element -->
......
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