Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
BookingMyHrManagement
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chanachai
BookingMyHrManagement
Commits
f2f0f2ae
Commit
f2f0f2ae
authored
May 19, 2025
by
DESKTOP-E0VCCBD\zedan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
c2ed17fe
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
647 additions
and
500 deletions
+647
-500
admin_dashboard_controller.cpython-312.pyc
...rs/__pycache__/admin_dashboard_controller.cpython-312.pyc
+0
-0
notification_controller.cpython-312.pyc
...llers/__pycache__/notification_controller.cpython-312.pyc
+0
-0
admin_dashboard_controller.py
API-Fast/src/controllers/admin_dashboard_controller.py
+45
-6
notification_controller.py
API-Fast/src/controllers/notification_controller.py
+0
-0
borrow_transaction.cpython-312.pyc
...src/models/__pycache__/borrow_transaction.cpython-312.pyc
+0
-0
borrow_transaction.py
API-Fast/src/models/borrow_transaction.py
+0
-1
admin_dashboard_schema.cpython-312.pyc
...chemas/__pycache__/admin_dashboard_schema.cpython-312.pyc
+0
-0
notification_schema.cpython-312.pyc
...c/schemas/__pycache__/notification_schema.cpython-312.pyc
+0
-0
admin_dashboard_schema.py
API-Fast/src/schemas/admin_dashboard_schema.py
+6
-1
home-common.component.html
...src/app/DPU/common/home-common/home-common.component.html
+7
-33
home-common.component.ts
...e/src/app/DPU/common/home-common/home-common.component.ts
+29
-22
user-setting.component.html
.../user-management/user-setting/user-setting.component.html
+2
-2
admin-project-emp-manage.component.ts
...-project-emp-manage/admin-project-emp-manage.component.ts
+24
-21
admin-project-equirement.component.html
...roject-equirement/admin-project-equirement.component.html
+9
-2
admin-project-equirement.component.ts
...-project-equirement/admin-project-equirement.component.ts
+28
-1
emp-borrow-return-status.component.html
...row-return-status/emp-borrow-return-status.component.html
+0
-94
emp-borrow-return-status.component.ts
...orrow-return-status/emp-borrow-return-status.component.ts
+2
-2
home-installer.component.html
...y-management/home-installer/home-installer.component.html
+10
-35
home-installer.component.ts
...any-management/home-installer/home-installer.component.ts
+304
-139
dasbord.model.ts
Web-Manage/src/app/DPU/models/dasbord.model.ts
+8
-1
notification.model.ts
Web-Manage/src/app/DPU/models/notification.model.ts
+17
-0
equipment-repair.servic.ts
Web-Manage/src/app/DPU/services/equipment-repair.servic.ts
+0
-27
notification.service.ts
Web-Manage/src/app/DPU/services/notification.service.ts
+100
-0
project-equipments.service.ts
...Manage/src/app/DPU/services/project-equipments.service.ts
+1
-0
login.component.html
Web-Manage/src/app/authentication/login/login.component.html
+1
-1
header.component.html
...ge/src/app/shared/components/header/header.component.html
+3
-104
header.component.ts
...nage/src/app/shared/components/header/header.component.ts
+46
-3
sidebar.component.html
.../src/app/shared/components/sidebar/sidebar.component.html
+3
-3
th.json
Web-Manage/src/assets/i18n/th.json
+2
-2
No files found.
API-Fast/src/controllers/__pycache__/admin_dashboard_controller.cpython-312.pyc
View file @
f2f0f2ae
No preview for this file type
API-Fast/src/controllers/__pycache__/notification_controller.cpython-312.pyc
View file @
f2f0f2ae
No preview for this file type
API-Fast/src/controllers/admin_dashboard_controller.py
View file @
f2f0f2ae
...
...
@@ -114,17 +114,56 @@ async def get_admin_dashboard(
]
# --- 3) EQUIPMENT DISTRIBUTION ---
stmt2
=
select
(
stmt2
=
(
select
(
Equipment
.
equipmentName
,
func
.
coalesce
(
func
.
sum
(
ProjectEquipment
.
quantity_in_project
),
0
)
.
label
(
'count'
)
)
.
join
(
ProjectEquipment
,
Equipment
.
equipmentId
==
ProjectEquipment
.
equipmentId
)
# จำนวนที่มีอยู่ในโครงการ
func
.
coalesce
(
func
.
sum
(
ProjectEquipment
.
quantity_in_project
),
0
)
.
label
(
'count'
),
# ยอด 'ชิ้น' ที่ถูกยืม / คืน (quantity_borrowed)
func
.
coalesce
(
func
.
sum
(
case
((
BorrowTransaction
.
status
!=
'returned'
,
BorrowTransaction
.
quantity_borrowed
),
else_
=
0
)
),
0
,
)
.
label
(
'qty_borrowed'
),
func
.
coalesce
(
func
.
sum
(
case
((
BorrowTransaction
.
status
==
'returned'
,
BorrowTransaction
.
quantity_borrowed
),
else_
=
0
)
),
0
,
)
.
label
(
'qty_returned'
),
# -------- ใหม่: นับ "ครั้ง" ที่ยืม/คืน --------
func
.
count
(
case
((
BorrowTransaction
.
status
!=
'returned'
,
BorrowTransaction
.
peId
),
else_
=
None
)
)
.
label
(
'borrow_times'
),
func
.
count
(
case
((
BorrowTransaction
.
status
==
'returned'
,
BorrowTransaction
.
peId
),
else_
=
None
)
)
.
label
(
'return_times'
),
)
.
join
(
ProjectEquipment
,
Equipment
.
equipmentId
==
ProjectEquipment
.
equipmentId
)
.
outerjoin
(
BorrowTransaction
,
BorrowTransaction
.
peId
==
ProjectEquipment
.
peId
)
)
stmt2
=
pe_filter
(
stmt2
)
.
group_by
(
Equipment
.
equipmentName
)
rows2
=
(
await
db
.
execute
(
stmt2
))
.
all
()
equipment_distribution
=
[
PieSlice
(
category
=
name
,
count
=
int
(
cnt
))
for
name
,
cnt
in
rows2
]
{
"category"
:
name
,
"count"
:
int
(
total_in_project
),
# stock ในโครงการ
"qty_borrowed"
:
int
(
qty_b
),
# ชิ้นที่ถูกยืมสะสม
"qty_returned"
:
int
(
qty_r
),
# ชิ้นที่คืนสะสม
"borrow_times"
:
int
(
bt_borrow
),
# ครั้งที่ยืม
"return_times"
:
int
(
bt_return
),
# ครั้งที่คืน
"percent_returned"
:
round
((
qty_r
/
qty_b
*
100
),
2
)
if
qty_b
else
0.0
,
}
for
name
,
total_in_project
,
qty_b
,
qty_r
,
bt_borrow
,
bt_return
in
rows2
]
# --- 4) BORROW/RETURN LINE ---
stmt3
=
(
...
...
API-Fast/src/controllers/notification_controller.py
View file @
f2f0f2ae
API-Fast/src/models/__pycache__/borrow_transaction.cpython-312.pyc
View file @
f2f0f2ae
No preview for this file type
API-Fast/src/models/borrow_transaction.py
View file @
f2f0f2ae
...
...
@@ -8,7 +8,6 @@ from ..config.database import Base
class
BorrowTransaction
(
Base
):
__tablename__
=
"borrow_transactions"
borrowId
=
Column
(
UUID
(
as_uuid
=
True
),
primary_key
=
True
,
default
=
uuid4
)
peId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"project_equipment.peId"
),
nullable
=
False
)
memberId
=
Column
(
UUID
(
as_uuid
=
True
),
ForeignKey
(
"member.memberId"
),
nullable
=
False
)
...
...
API-Fast/src/schemas/__pycache__/admin_dashboard_schema.cpython-312.pyc
View file @
f2f0f2ae
No preview for this file type
API-Fast/src/schemas/__pycache__/notification_schema.cpython-312.pyc
View file @
f2f0f2ae
No preview for this file type
API-Fast/src/schemas/admin_dashboard_schema.py
View file @
f2f0f2ae
...
...
@@ -14,8 +14,13 @@ class TrendItem(BaseModel):
returned
:
int
class
PieSlice
(
BaseModel
):
category
:
str
# เช่น ชื่ออุปกรณ์ หรือ "Returned"/"Borrowed"
category
:
str
count
:
int
qty_borrowed
:
int
# เดิมใช้ borrowed → เปลี่ยนชื่อให้ตรงกับ controller
qty_returned
:
int
# เดิมใช้ returned → เปลี่ยนชื่อให้ตรงกับ controller
borrow_times
:
int
# ใหม่: จำนวน "ครั้ง" ที่ยืม
return_times
:
int
# ใหม่: จำนวน "ครั้ง" ที่คืน
percent_returned
:
float
class
AdminDashboardResponse
(
BaseModel
):
period
:
dict
# {"start": date, "end": date}
...
...
Web-Manage/src/app/DPU/common/home-common/home-common.component.html
View file @
f2f0f2ae
...
...
@@ -160,11 +160,11 @@
<div
class=
"grid grid-cols-2 border-t border-dashed dark:border-defaultborder/10"
>
<div
class=
"col p-4 border-e border-dashed dark:border-defaultborder/10 text-center"
>
<div
class=
"text-[#8c9097] dark:text-white/50 text-[0.75rem] mb-1"
>
การ
ยืมทั้งหมด
จำนวน
ยืมทั้งหมด
</div>
<div
class=
"flex justify-center items-center"
>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
1,234
</span>
<span
class=
"text-success font-semibold"
><i
class=
"ri-arrow-up-s-fill me-1"
></i>
0.23%
</span>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
{{ totalBorrowedChart }} ครั้ง
</span>
</div>
</div>
<div
class=
"col p-4 text-center"
>
...
...
@@ -172,8 +172,8 @@
การคืนทั้งหมด
</div>
<div
class=
"flex justify-center items-center"
>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
1,754
</span>
<span
class=
"text-danger font-semibold"
><i
class=
"ri-arrow-down-s-fill me-1"
></i>
0.11%
</span>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
{{ totalReturnedChart }} ครั้ง
</span>
</div>
</div>
</div>
...
...
@@ -188,19 +188,6 @@
<div
class=
"box-title"
>
จำนวนอุปกรณ์คงเหลือ
</div>
<div
class=
"flex gap-4 flex-wrap"
>
<div
class=
"inline-flex rounded-md shadow-sm"
role=
"group"
aria-label=
"Basic example"
>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
1M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
3M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
6M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary-full !rounded-s-none !text-white"
>
1Y
</button>
</div>
</div>
</div>
...
...
@@ -222,26 +209,13 @@
</div>
</div>
<div
class=
"xxl:col-span-6 col-span-12"
>
<
!-- <
div class="xxl:col-span-6 col-span-12">
<div class="box custom-box">
<div class="box-header justify-between items-center flex-wrap gap-4">
<div class="box-title">จำนวนอุปกรณ์ทั้งหมด</div>
<div class="flex gap-4 flex-wrap">
<div class="inline-flex rounded-md shadow-sm" role="group" aria-label="Basic example">
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
1M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
3M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
6M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary-full !rounded-s-none !text-white"
>
1Y
</button>
</div>
</div>
</div>
...
...
@@ -260,4 +234,4 @@
</div>
</div>
</div>
</div>
</div>
-->
Web-Manage/src/app/DPU/common/home-common/home-common.component.ts
View file @
f2f0f2ae
...
...
@@ -40,6 +40,9 @@ export class HomeCommonComponent {
@
ViewChild
(
'closeModal'
)
public
childModal
?:
ElementRef
;
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
totalBorrowedChart
:
number
=
0
;
totalReturnedChart
:
number
=
0
;
totalBorrowed
:
number
=
0
;
action
=
"new"
;
rawData
:
any
[];
allSelected
=
false
;
...
...
@@ -104,7 +107,7 @@ export class HomeCommonComponent {
colors
:
[
'#23b7e5'
],
xaxis
:
{
categories
:
[]
as
string
[],
title
:
{
text
:
'อุปกรณ์'
}
},
yaxis
:
{
title
:
{
text
:
'จำนวนคงเหลือ'
}
...
...
@@ -356,15 +359,6 @@ export class HomeCommonComponent {
this
.
selectedProjects
=
this
.
selectedProjects
.
filter
(
p
=>
p
!==
value
);
}
}
toggleDropdown
()
{
this
.
isDropdownOpen
=
!
this
.
isDropdownOpen
;
}
toggleDropdown1
()
{
this
.
isDropdownOpen1
=
!
this
.
isDropdownOpen1
;
}
getSelected
():
string
{
const
selectedIds
=
Object
.
keys
(
this
.
itemSelection
).
filter
(
...
...
@@ -396,7 +390,7 @@ export class HomeCommonComponent {
this
.
equipmentList
=
result
})
const
today
=
new
Date
();
const
firstDay
=
new
Date
(
today
.
getFullYear
(),
today
.
getMonth
()
,
1
);
const
firstDay
=
new
Date
(
today
.
getFullYear
(),
0
,
1
);
this
.
startDate
=
this
.
formatDateToYYYYMMDD
(
firstDay
);
this
.
endDate
=
this
.
formatDateToYYYYMMDD
(
today
);
this
.
getDashbord
()
...
...
@@ -406,24 +400,16 @@ export class HomeCommonComponent {
this
.
DashboardService
.
getDashboard
(
this
.
startDate
,
this
.
endDate
).
subscribe
(
result
=>
{
this
.
dashboardModel
=
result
this
.
updateChart
(
this
.
dashboardModel
)
this
.
updateDonut
(
this
.
dashboardModel
.
equipment_distribution
)
this
.
updateDonut
(
this
.
dashboardModel
.
equipment_distribution
)
;
this
.
mapStockChart
(
this
.
dashboardModel
.
equipment_distribution
);
this
.
mapEquipmentChart
(
this
.
dashboardModel
.
equipment_distribution
);
console
.
log
(
this
.
dashboardModel
)
})
}
private
updateDonut
(
data
:
Equipmentdistribution
[])
{
// series = array of counts
this
.
optionsCircle1
.
series
=
data
.
map
(
item
=>
item
.
count
);
// labels = array of categories
this
.
optionsCircle1
.
labels
=
data
.
map
(
item
=>
item
.
category
);
}
private
updateChart
(
data
:
DashboardModel
)
{
// แมป monthly_trends ไปเป็น series + categories
const
trends
=
data
.
monthly_trends
;
this
.
chartOptions9
.
series
=
[
{
name
:
'จำนวนการยืม'
,
data
:
trends
.
map
(
t
=>
t
.
borrowed
)
},
{
name
:
'จำนวนการคืน'
,
data
:
trends
.
map
(
t
=>
t
.
returned
)
},
...
...
@@ -432,7 +418,28 @@ export class HomeCommonComponent {
...
this
.
chartOptions9
.
xaxis
,
categories
:
trends
.
map
(
t
=>
t
.
period
)
};
}
// ✅ คำนวณยอดรวมทั้งหมด
this
.
totalBorrowedChart
=
trends
.
map
(
t
=>
t
.
borrowed
).
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
this
.
totalReturnedChart
=
trends
.
map
(
t
=>
t
.
returned
).
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
}
private
updateDonut
(
data
:
Equipmentdistribution
[])
{
const
series
=
data
.
map
(
d
=>
d
.
qty_borrowed
);
const
labels
=
data
.
map
(
d
=>
d
.
category
);
console
.
log
(
"Donut updated:"
,
series
,
labels
);
this
.
totalBorrowed
=
series
.
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
// 👈 รวม total ไว้ใช้ใน HTML
this
.
optionsCircle1
=
{
...
this
.
optionsCircle1
,
series
,
labels
,
};
}
private
mapStockChart
(
dist
:
Equipmentdistribution
[])
{
// data = quantity ของแต่ละอุปกรณ์
...
...
Web-Manage/src/app/DPU/common/user-management/user-setting/user-setting.component.html
View file @
f2f0f2ae
...
...
@@ -279,8 +279,8 @@
<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-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"
>
...
...
Web-Manage/src/app/DPU/company-management/admin-project-emp-manage/admin-project-emp-manage.component.ts
View file @
f2f0f2ae
...
...
@@ -36,6 +36,7 @@ export class AdminProjectEmpManageComponent {
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
action
=
"new"
;
allSelected
=
false
;
projectMembers
:
ProjectMemberModel
[]
=
[];
someSelected
=
false
;
confirmPassword
=
""
itemsList
:
ProjectMemberModel
[]
=
[]
...
...
@@ -63,8 +64,9 @@ export class AdminProjectEmpManageComponent {
this
.
updatePagedItems
()
}
}
projectId
=
""
_searchTerm
=
""
;
projectId
=
""
hisList
:
BorrowTransactionsModel
[]
=
[]
constructor
(
private
projectMemberService
:
ProjectMemberService
,
private
userService
:
UserService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
,
private
borrowTransactionsService
:
BorrowTransactionsService
)
{
this
.
projectId
=
this
.
tokenService
.
getSelectCompany
().
projectId
!
;
...
...
@@ -204,35 +206,36 @@ export class AdminProjectEmpManageComponent {
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
}).
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
if
(
this
.
action
==
'add'
)
{
this
.
projectMemberService
.
getLists
(
this
.
projectId
).
subscribe
(
members
=>
{
this
.
projectMembers
=
members
;
const
isDuplicate
=
this
.
projectMembers
.
some
(
m
=>
m
.
memberId
===
item
.
memberId
);
if
(
this
.
action
===
'add'
)
{
if
(
isDuplicate
)
{
swal
(
"เกิดข้อผิดพลาด"
,
"สมาชิกนี้ถูกเพิ่มแล้ว"
,
"error"
);
return
;
}
this
.
projectMemberService
.
save
({
"memberId"
:
item
.
memberId
,
"role_in_project"
:
"employee"
,
"projectId"
:
this
.
projectId
memberId
:
item
.
memberId
,
role_in_project
:
"employee"
,
projectId
:
this
.
projectId
}).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
getUserProject
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
else
if
(
this
.
action
==
'edit'
)
{
this
.
getUserProject
();
this
.
childModal
?.
nativeElement
.
click
();
});
}
else
if
(
this
.
action
=
==
'edit'
)
{
this
.
projectMemberService
.
update
(
this
.
selectModel
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Update Success!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
getUserProject
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
this
.
getUserProject
();
this
.
childModal
?.
nativeElement
.
click
();
});
}
});
}
});
}
updatePagedItems
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
...
...
Web-Manage/src/app/DPU/company-management/admin-project-equirement/admin-project-equirement.component.html
View file @
f2f0f2ae
...
...
@@ -131,6 +131,14 @@
>
<i
class=
"ri-tools-line"
></i>
</button>
<!-- <button
*ngIf="borrowSelect?.quantity_borrowed === 0"
type="button"
class="ti-btn ti-btn-sm ti-btn-danger me-0"
(click)="deleteEquipment()">
<i class="ri-delete-bin-line"></i>
</button> -->
</div>
</div>
</div>
...
...
@@ -225,9 +233,8 @@
<div
class=
"font-semibold mb-1"
>
จำนวน :
</div>
<!-- <h3 class="text-[#8c9097] dark:text-white/50">{{item.quantity}}</h3> -->
<input
t
ype=
"number"
ype=
"number"
class=
"form-control"
id=
"deal-name"
placeholder=
"จำนวน"
[(
ngModel
)]="
item
.
quantity
"
/>
...
...
Web-Manage/src/app/DPU/company-management/admin-project-equirement/admin-project-equirement.component.ts
View file @
f2f0f2ae
...
...
@@ -49,7 +49,7 @@ export class AdminProjectEquirementComponent {
itemsListAll
:
EquipmentModel
[]
=
[]
filterListAll
:
EquipmentModel
[]
=
[]
selectModel
:
ProjectEquipmentModel
=
new
ProjectEquipmentModel
()
selectStock
?
:
EquipmentStockModel
selectStock
:
EquipmentStockModel
selectedItems
=
new
Map
<
string
,
boolean
>
();
borrowSelect
:
BorrowTransactionsModel
=
new
BorrowTransactionsModel
()
pageIndex
=
0
;
...
...
@@ -119,6 +119,32 @@ export class AdminProjectEquirementComponent {
);
}
deleteEquipment
(
item
?:
EquipmentModel
)
{
if
(
!
item
)
return
;
swal
({
title
:
"ลบรายการ?"
,
text
:
"คุณต้องการลบอุปกรณ์นี้หรือไม่"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"ยกเลิก"
,
"ลบ"
],
}).
then
((
willDelete
)
=>
{
if
(
willDelete
)
{
this
.
eqService
.
delete
(
item
).
subscribe
({
next
:
()
=>
{
swal
(
"ลบสำเร็จ"
,
"อุปกรณ์ถูกลบแล้ว"
,
"success"
);
this
.
ngOnInit
();
},
error
:
(
error
)
=>
{
swal
(
"เกิดข้อผิดพลาด"
,
error
.
error
.
detail
||
"ไม่สามารถลบได้"
,
"error"
);
}
});
}
});
}
delete
(
item
:
EquipmentModel
)
{
swal
({
title
:
"Are you sure?"
,
...
...
@@ -310,6 +336,7 @@ export class AdminProjectEquirementComponent {
}
stock
(
item
:
EquipmentModel
)
{
if
(
item
.
quantity
>
0
)
{
swal
({
...
...
Web-Manage/src/app/DPU/company-management/emp-borrow-return-status/emp-borrow-return-status.component.html
View file @
f2f0f2ae
...
...
@@ -290,100 +290,6 @@
</div>
</div>
</div>
<!-- Start:: New Deal -->
<div
id=
"modal-repair"
class=
"hs-overlay hidden ti-modal"
*
ngIf=
"selectModel"
>
<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=
"#modal-repair"
>
<span
class=
"sr-only"
>
Close
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<img
[
src
]="
selectModel
.
equipment
.
getPicture
()"
class=
"!rounded-t-md"
alt=
"..."
style=
"width: 100%; height: auto; object-fit: cover"
/>
</div>
<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=
"input-label"
class=
"form-label"
>
{{
"สถานะ" | translate
}}
</label>
<!-- <ng-select [items]="customerList" bindLabel="companyThName" [(ngModel)]="projectModel.customer">
</ng-select> -->
<select
class=
"mb-4 sm:mb-0 form-select !py-3"
id=
"inlineFormSelectPref"
[(
ngModel
)]="
borrowSelect
.
status
"
>
<option
ngValue=
"repair"
selected
>
ส่งซ่อม
</option>
<option
ngValue=
"remove"
selected
>
นำอุปกรณ์ออก
</option>
</select>
<!-- <select class="mb-4 sm:mb-0 form-select !py-3" id="inlineFormSelectPref"
[(ngModel)]="projectModel.customer">
<option [ngValue]="null" selected>-</option>
<option *ngFor="let item of customerList" [ngValue]="item">{{item.getCompanyName()}}</option>
</select> -->
</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=
"deal-name"
placeholder=
"จำนวนที่ชำรุด"
[(
ngModel
)]="
selectedBorrowItem
.
quantity_borrowed
"
/>
</div>
</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=
"#modal-repair"
>
ยกเลิก
</button>
<button
type=
"button"
class=
"ti-btn bg-primary text-white !font-medium"
(
click
)="
saveRepair
()"
>
บันทึก
</button>
</div>
</div>
</div>
</div>
<div
id=
"detail-borrow"
class=
"hs-overlay hidden ti-modal"
...
...
Web-Manage/src/app/DPU/company-management/emp-borrow-return-status/emp-borrow-return-status.component.ts
View file @
f2f0f2ae
...
...
@@ -22,6 +22,7 @@ import { ChangeDetectorRef } from '@angular/core';
import
{
Subject
}
from
'rxjs'
;
import
{
takeUntil
}
from
'rxjs/operators'
;
import
{
UserProfileModel
}
from
'../../models/user.model'
;
import
{
FileUploader
}
from
'ng2-file-upload'
;
...
...
@@ -140,6 +141,7 @@ quantityExceeded: boolean = false;
this
.
applyFilter
();
}
applyFilter
():
void
{
let
filtered
=
[...
this
.
hisList
];
...
...
@@ -383,6 +385,4 @@ quantityExceeded: boolean = false;
this
.
filterListAll
=
this
.
itemsListAll
}
}
Web-Manage/src/app/DPU/company-management/home-installer/home-installer.component.html
View file @
f2f0f2ae
...
...
@@ -53,7 +53,7 @@
<div
class=
"flex-grow"
>
<div
class=
"flex mb-1 items-start justify-between"
>
<h5
class=
"font-semibold mb-0 leading-none text-[1.25rem]"
>
{{ itemsList
.length }}
{{ itemsList1
.length }}
</h5>
<div
class=
"text-danger font-semibold"
></div>
</div>
...
...
@@ -84,7 +84,7 @@
<div
class=
"flex-grow"
>
<div
class=
"flex mb-1 items-start justify-between"
>
<h5
class=
"font-semibold mb-0 leading-none text-[1.25rem]"
>
{{
projectList
.length }}
{{
itemsList2
.length }}
</h5>
<div
class=
"text-success font-semibold"
></div>
</div>
...
...
@@ -113,7 +113,7 @@
<div
class=
"flex-grow"
>
<div
class=
"flex mb-1 items-start justify-between"
>
<h5
class=
"font-semibold mb-0 leading-none text-[1.25rem]"
>
{{
equipment
List.length }}
{{
items
List.length }}
</h5>
<div
class=
"text-success font-semibold"
></div>
</div>
...
...
@@ -167,8 +167,8 @@
การยืมทั้งหมด
</div>
<div
class=
"flex justify-center items-center"
>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
1,234
</span>
<span
class=
"text-success font-semibold"
><i
class=
"ri-arrow-up-s-fill me-1"
></i>
0.23%
</span>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
{{ totalBorrowedChart }} ครั้ง
</span>
</div>
</div>
<div
class=
"col p-4 text-center"
>
...
...
@@ -176,8 +176,8 @@
การคืนทั้งหมด
</div>
<div
class=
"flex justify-center items-center"
>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
1,754
</span>
<span
class=
"text-danger font-semibold"
><i
class=
"ri-arrow-down-s-fill me-1"
></i>
0.11%
</span>
<span
class=
"me-3 text-[1.625rem] font-semibold"
>
{{ totalReturnedChart }} ครั้ง
</span>
</div>
</div>
</div>
...
...
@@ -192,19 +192,6 @@
<div
class=
"box-title"
>
จำนวนอุปกรณ์คงเหลือ
</div>
<div
class=
"flex gap-4 flex-wrap"
>
<div
class=
"inline-flex rounded-md shadow-sm"
role=
"group"
aria-label=
"Basic example"
>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
1M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
3M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
6M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary-full !rounded-s-none !text-white"
>
1Y
</button>
</div>
</div>
</div>
...
...
@@ -226,26 +213,13 @@
</div>
</div>
<div
class=
"xxl:col-span-6 col-span-12"
>
<
!-- <
div class="xxl:col-span-6 col-span-12">
<div class="box custom-box">
<div class="box-header justify-between items-center flex-wrap gap-4">
<div class="box-title">จำนวนอุปกรณ์ทั้งหมด</div>
<div class="flex gap-4 flex-wrap">
<div class="inline-flex rounded-md shadow-sm" role="group" aria-label="Basic example">
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
1M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
3M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary"
>
6M
</button>
<button
type=
"button"
class=
"ti-btn-group !border-0 !text-xs !py-2 !px-3 ti-btn-primary-full !rounded-s-none !text-white"
>
1Y
</button>
</div>
</div>
</div>
...
...
@@ -264,4 +238,5 @@
</div>
</div>
</div>
</div>
</div> -->
Web-Manage/src/app/DPU/company-management/home-installer/home-installer.component.ts
View file @
f2f0f2ae
import
{
NotificationModel
}
from
'./../../models/notification.model'
;
import
{
NotificationService
}
from
'./../../services/notification.service'
;
import
{
DashboardService
}
from
'./../../services/dashboard.service'
;
import
{
EquipmentService
}
from
'./../../services/equirement.service'
;
import
{
ProjectService
}
from
'./../../services/project.service'
;
...
...
@@ -21,8 +23,14 @@ import { environment } from '../../../../environments/environment';
import
swal
from
'sweetalert'
;
import
{
ProjectModel
}
from
'../../models/project.model'
;
import
{
EquipmentModel
}
from
'../../models/equipments.model'
;
import
{
DashboardModel
}
from
'../../models/dasbord.model'
;
import
{
DashboardModel
,
Equipmentdistribution
,
Summary
}
from
'../../models/dasbord.model'
;
import
{
CompanyService
}
from
'../../services/company.service'
;
import
{
Subscription
}
from
'rxjs'
;
import
{
OnInit
,
OnDestroy
}
from
'@angular/core'
;
import
{
ProjectEquipmentService
}
from
'../../services/project-equipments.service'
;
import
{
ProjectEquipmentModel
}
from
'../../models/project-equipments'
;
import
{
ProjectMemberModel
}
from
'../../models/project-members'
;
import
{
ProjectMemberService
}
from
'../../services/project-members.service'
;
@
Component
({
selector
:
'app-home-installer'
,
...
...
@@ -42,8 +50,15 @@ export class HomeInstallerComponent {
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
action
=
"new"
;
rawData
:
any
[];
summary
:
Summary
[]
=
[];
totalBorrowedChart
:
number
=
0
;
totalReturnedChart
:
number
=
0
;
userCount
=
0
;
projectCount
=
0
;
equipmentCount
=
0
;
allSelected
=
false
;
someSelected
=
false
;
itemSelection
:
{
[
key
:
string
]:
boolean
}
=
{};
startDate
:
string
=
''
;
endDate
:
string
=
''
;
selectedProjects
:
string
[]
=
[];
...
...
@@ -54,8 +69,12 @@ export class HomeInstallerComponent {
dashbordList
:
string
[]
=
[];
equipmentList
:
EquipmentModel
[]
=
[]
projectList
:
ProjectModel
[]
=
[]
itemsList
:
UserProfileModel
[]
=
[]
filterList
:
UserProfileModel
[]
=
[]
itemsList
:
ProjectEquipmentModel
[]
=
[]
itemsList1
:
ProjectMemberModel
[]
=
[]
itemsList2
:
ProjectModel
[]
=
[]
filterList2
:
ProjectModel
[]
=
[]
filterList
:
ProjectEquipmentModel
[]
=
[]
filterList1
:
ProjectMemberModel
[]
=
[]
selectModel
:
UserProfileModel
=
new
UserProfileModel
()
selectedItems
=
new
Map
<
string
,
boolean
>
();
roleList
:
UserRoleModel
[]
=
[]
...
...
@@ -268,7 +287,7 @@ export class HomeInstallerComponent {
},
};
projectId
=
""
constructor
(
private
el
:
ElementRef
,
private
renderer
:
Renderer2
,
private
cdr
:
ChangeDetectorRef
,
private
userService
:
UserService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
,
private
projectService
:
ProjectService
,
private
EquipmentService
:
EquipmentService
,
private
DashboardService
:
DashboardService
,
private
route
:
ActivatedRoute
,
private
comService
:
ProjectService
)
{
constructor
(
private
projectMemberService
:
ProjectMemberService
,
private
projectEquipmentService
:
ProjectEquipmentService
,
private
el
:
ElementRef
,
private
renderer
:
Renderer2
,
private
cdr
:
ChangeDetectorRef
,
private
userService
:
UserService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
,
private
projectService
:
ProjectService
,
private
EquipmentService
:
EquipmentService
,
private
DashboardService
:
DashboardService
,
private
route
:
ActivatedRoute
,
private
comService
:
ProjectService
)
{
this
.
projectId
=
this
.
route
.
snapshot
.
paramMap
.
get
(
'projectId'
)
!
;
this
.
projectService
.
getById
(
this
.
projectId
).
subscribe
(
result
=>
{
console
.
log
(
"SAVEEE"
)
...
...
@@ -330,6 +349,14 @@ export class HomeInstallerComponent {
};
}
formatDateToYYYYMMDD
(
date
:
Date
):
string
{
const
year
=
date
.
getFullYear
();
const
month
=
(
date
.
getMonth
()
+
1
).
toString
().
padStart
(
2
,
'0'
);
// เพิ่ม 1 เพราะเดือนเริ่มที่ 0
const
day
=
date
.
getDate
().
toString
().
padStart
(
2
,
'0'
);
return
`
${
year
}
-
${
month
}
-
${
day
}
`
;
}
onProjectCheckboxChange
(
event
:
any
)
{
const
value
=
event
.
target
.
value
;
...
...
@@ -339,63 +366,215 @@ export class HomeInstallerComponent {
this
.
selectedProjects
=
this
.
selectedProjects
.
filter
(
p
=>
p
!==
value
);
}
}
toggleDropdown
()
{
this
.
isDropdownOpen
=
!
this
.
isDropdownOpen
;
}
getdasbord
()
{
this
.
DashboardService
.
getDashboard
(
this
.
startDate
,
this
.
endDate
,)
.
subscribe
(
data
=>
{
console
.
log
(
'Dashboard Data:'
,
data
);
});
getSelected
():
string
{
const
selectedIds
=
Object
.
keys
(
this
.
itemSelection
).
filter
(
id
=>
this
.
itemSelection
[
id
]
);
if
(
selectedIds
.
length
===
0
)
return
'เลือกอุปกรณ์'
;
if
(
selectedIds
.
length
===
this
.
equipmentList
.
length
)
return
'อุปกรณ์ทั้งหมด'
;
const
selectedNames
=
this
.
equipmentList
.
filter
(
equipmentList
=>
selectedIds
.
includes
(
equipmentList
.
equipmentName
))
.
map
(
equipmentList
=>
equipmentList
.
equipmentName
);
return
selectedNames
.
join
(
', '
);
}
ngOnInit
():
void
{
this
.
userService
.
getLists
().
subscribe
(
result
=>
{
this
.
itemsList
=
result
this
.
updatePagedItems
()
})
this
.
projectService
.
getLists
().
subscribe
(
result
=>
{
this
.
projectList
=
result
})
this
.
EquipmentService
.
getLists
().
subscribe
(
result
=>
{
this
.
equipmentList
=
result
})
const
today
=
new
Date
();
const
firstDay
=
new
Date
(
today
.
getFullYear
(),
today
.
getMonth
(),
1
);
// เดือน 0 = มกราคม
const
firstDay
=
new
Date
(
today
.
getFullYear
(),
0
,
1
);
this
.
startDate
=
this
.
formatDateToYYYYMMDD
(
firstDay
);
this
.
endDate
=
this
.
formatDateToYYYYMMDD
(
today
);
this
.
getDashbord
()
this
.
getProjectEquirment
()
this
.
getUserProject
()
this
.
getProject
()
}
getDashbord
()
{
this
.
DashboardService
.
getDashboard
(
this
.
startDate
,
this
.
endDate
).
subscribe
(
result
=>
{
this
.
dashboardModel
=
result
console
.
log
(
this
.
dashboardModel
)
})
this
.
DashboardService
.
getDashboard
(
this
.
startDate
,
this
.
endDate
,
this
.
projectId
).
subscribe
(
result
=>
{
this
.
dashboardModel
=
result
;
this
.
mapSummary
(
this
.
dashboardModel
.
summary
);
this
.
updateChart
(
this
.
dashboardModel
);
this
.
updateDonut
(
this
.
dashboardModel
.
equipment_distribution
);
this
.
mapStockChart
(
this
.
dashboardModel
.
equipment_distribution
);
this
.
mapEquipmentChart
(
this
.
dashboardModel
.
equipment_distribution
);
console
.
log
(
this
.
dashboardModel
);
});
}
private
updateDonut
(
data
:
Equipmentdistribution
[])
{
// series = array of counts
this
.
optionsCircle1
.
series
=
data
.
map
(
item
=>
item
.
qty_borrowed
);
// labels = array of categories
this
.
optionsCircle1
.
labels
=
data
.
map
(
item
=>
item
.
category
);
}
formatDateToYYYYMMDD
(
date
:
Date
):
string
{
const
year
=
date
.
getFullYear
();
const
month
=
(
date
.
getMonth
()
+
1
).
toString
().
padStart
(
2
,
'0'
);
// เพิ่ม 1 เพราะเดือนเริ่มที่ 0
const
day
=
date
.
getDate
().
toString
().
padStart
(
2
,
'0'
);
return
`
${
year
}
-
${
month
}
-
${
day
}
`
;
private
updateChart
(
data
:
DashboardModel
)
{
const
trends
=
data
.
monthly_trends
;
this
.
chartOptions9
.
series
=
[
{
name
:
'จำนวนการยืม'
,
data
:
trends
.
map
(
t
=>
t
.
borrowed
)
},
{
name
:
'จำนวนการคืน'
,
data
:
trends
.
map
(
t
=>
t
.
returned
)
},
];
this
.
chartOptions9
.
xaxis
=
{
...
this
.
chartOptions9
.
xaxis
,
categories
:
trends
.
map
(
t
=>
t
.
period
)
};
// ✅ คำนวณยอดรวมทั้งหมด
this
.
totalBorrowedChart
=
trends
.
map
(
t
=>
t
.
borrowed
).
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
this
.
totalReturnedChart
=
trends
.
map
(
t
=>
t
.
returned
).
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
}
private
mapStockChart
(
dist
:
Equipmentdistribution
[])
{
// data = quantity ของแต่ละอุปกรณ์
this
.
chartStockOptions
.
series
[
0
].
data
=
dist
.
map
(
x
=>
x
.
count
);
// labels = ชื่ออุปกรณ์
this
.
chartStockOptions
.
xaxis
.
categories
=
dist
.
map
(
x
=>
x
.
category
);
}
private
mapEquipmentChart
(
dist
:
Equipmentdistribution
[])
{
this
.
chartEquipmentOptions
.
series
[
0
].
data
=
dist
.
map
(
x
=>
x
.
count
);
this
.
chartEquipmentOptions
.
xaxis
.
categories
=
dist
.
map
(
x
=>
x
.
category
);
}
private
mapSummary
(
summary
:
Summary
[])
{
this
.
summary
=
summary
;
const
user
=
summary
.
find
(
x
=>
x
.
label
===
'จำนวนผู้ใช้งาน'
);
const
project
=
summary
.
find
(
x
=>
x
.
label
===
'จำนวนโครงการ'
);
const
equipment
=
summary
.
find
(
x
=>
x
.
label
===
'จำนวนอุปกรณ์'
);
this
.
userCount
=
user
?.
value
??
0
;
this
.
projectCount
=
project
?.
value
??
0
;
this
.
equipmentCount
=
equipment
?.
value
??
0
;
}
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
.
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
x
.
equipment
.
equipmentName
.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
equipment
.
description
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
getProject
()
{
const
user
=
this
.
tokenService
.
getUser
();
const
memberId
=
user
?.
member
?.
memberId
;
if
(
memberId
)
{
// ดึงรายการ ProjectMemberModel ที่ user นี้ถูก assign ไว้
this
.
projectMemberService
.
getCompanyAdmin
(
memberId
).
subscribe
((
memberProjects
:
ProjectMemberModel
[])
=>
{
const
allowedProjectIds
=
memberProjects
.
filter
(
pm
=>
!!
pm
.
projectId
)
.
map
(
pm
=>
pm
.
projectId
);
this
.
projectService
.
getLists
().
subscribe
((
allProjects
:
ProjectModel
[])
=>
{
this
.
itemsList2
=
allProjects
.
filter
(
p
=>
p
.
projectId
&&
allowedProjectIds
.
includes
(
p
.
projectId
)
);
this
.
updatePagedItems2
();
});
});
}
}
getUserProject
()
{
this
.
projectMemberService
.
getLists
(
this
.
projectId
).
subscribe
(
result
=>
{
this
.
itemsList1
=
result
this
.
updatePagedItems1
()
})
}
updatePagedItems1
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
this
.
filterList1
=
this
.
itemsList1
.
slice
(
startIndex
,
endIndex
);
}
filter1
(
v
:
string
)
{
return
this
.
itemsList1
?.
filter
(
(
x
)
=>
x
.
member
.
memberId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
username
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
email
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
phoneNumber
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getRole
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getStatus
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
member
.
getFullname
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
toggleAll
(
event
:
any
)
{
this
.
allSelected
=
event
.
target
.
checked
;
this
.
selectedItems
.
clear
();
this
.
itemsList1
.
forEach
(
item
=>
{
this
.
selectedItems
.
set
(
item
.
memberId
,
this
.
allSelected
);
});
this
.
someSelected
=
this
.
itemsList1
.
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
.
itemsList1
.
every
(
item
=>
this
.
selectedItems
.
get
(
item
.
memberId
));
this
.
someSelected
=
this
.
itemsList1
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
memberId
));
}
updatePagedItems2
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
this
.
filterList2
=
this
.
itemsList2
.
slice
(
startIndex
,
endIndex
);
}
filter2
(
v
:
string
)
{
return
this
.
itemsList2
?.
filter
(
(
x
)
=>
x
.
projectId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
project_name
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
project_desc
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
toggleAll1
(
event
:
any
)
{
this
.
allSelected
=
event
.
target
.
checked
;
this
.
selectedItems
.
clear
();
this
.
itemsList2
.
forEach
(
item
=>
{
this
.
selectedItems
.
set
(
item
.
projectId
!
,
this
.
allSelected
);
});
this
.
someSelected
=
this
.
itemsList2
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
projectId
!
));
}
onCheckboxChange1
(
projectId
:
string
)
{
const
isSelected
=
this
.
selectedItems
.
get
(
projectId
)
||
false
;
this
.
selectedItems
.
set
(
projectId
,
!
isSelected
);
this
.
allSelected
=
this
.
itemsList2
.
every
(
item
=>
this
.
selectedItems
.
get
(
item
.
projectId
!
));
this
.
someSelected
=
this
.
itemsList2
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
projectId
!
));
}
delete
(
item
:
UserProfileModel
)
{
swal
({
...
...
@@ -465,115 +644,101 @@ export class HomeInstallerComponent {
}
applyFilters
()
{
const
selectedProjects
=
Object
.
keys
(
this
.
projectSelection
).
filter
(
p
=>
this
.
projectSelection
[
p
]);
// Filter your full data here
const
filteredData
=
this
.
rawData
.
filter
(
item
=>
{
return
(
!
this
.
startDate
||
item
.
date
>=
this
.
startDate
)
&&
(
!
this
.
endDate
||
item
.
date
<=
this
.
endDate
)
&&
(
selectedProjects
.
length
===
0
||
selectedProjects
.
includes
(
item
.
project_name
))
&&
(
this
.
selectedEquipmentType
===
'ALL'
||
item
.
equipment_type
===
this
.
selectedEquipmentType
);
});
}
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
.
userService
.
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
.
userService
.
update
(
user
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
();
});
}
}
});
}
});
}
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this
.
filterList
=
this
.
itemsList
}
// 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.userService.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.userService.update(user).subscribe(result => {
// swal("Save Success!!", "บันทึกข้อมูลสำเร็จ", "success");
// this.ngOnInit();
// });
// }
// }
// });
// }
// });
// }
filterEmp
(
empId
:
string
)
{
this
.
selectModel
=
this
.
empList
.
filter
(
e
=>
e
.
memberId
==
empId
)[
0
]
...
...
Web-Manage/src/app/DPU/models/dasbord.model.ts
View file @
f2f0f2ae
...
...
@@ -6,9 +6,16 @@ export interface DashboardModel {
borrow_return_line
:
Monthlytrend
[];
}
export
interface
Equipmentdistribution
{
category
:
string
;
count
:
number
;
count
:
number
;
// จำนวนสต็อกในโครงการ
qty_borrowed
:
number
;
// ยอด "ชิ้น" ที่ถูกยืมสะสม
qty_returned
:
number
;
// ยอดชิ้นที่คืนสะสม
borrow_times
:
number
;
// จำนวน "ครั้ง" ที่ยืม
return_times
:
number
;
// จำนวน "ครั้ง" ที่คืน
percent_returned
:
number
;
}
export
interface
Monthlytrend
{
...
...
Web-Manage/src/app/DPU/models/notification.model.ts
0 → 100644
View file @
f2f0f2ae
import
{
TranslateService
}
from
"@ngx-translate/core"
;
import
{
BaseModel
}
from
"./base.model"
;
export
class
NotificationModel
{
notifId
!
:
string
;
// UUID
projectId
!
:
string
;
// UUID
equipmentId
!
:
string
;
// UUID
message
!
:
string
;
isRead
=
false
;
createdAt
!
:
string
;
// ISO-string
constructor
(
init
?:
Partial
<
NotificationModel
>
)
{
Object
.
assign
(
this
,
init
);
// เผื่อใช้สร้าง object ฝั่ง client
}
}
Web-Manage/src/app/DPU/services/equipment-repair.servic.ts
deleted
100644 → 0
View file @
c2ed17fe
// 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
);
}
}
Web-Manage/src/app/DPU/services/notification.service.ts
0 → 100644
View file @
f2f0f2ae
import
{
TranslateService
}
from
'@ngx-translate/core'
;
import
{
PageResponseModel
}
from
'./../models/base.model'
;
import
{
Injectable
}
from
'@angular/core'
;
import
{
HttpClient
,
HttpParams
,
HttpHeaders
}
from
'@angular/common/http'
;
import
{
map
,
switchMap
,
forkJoin
,
Observable
,
catchError
,
of
}
from
'rxjs'
;
import
{
environment
}
from
'../../../environments/environment'
;
import
{
NotificationModel
}
from
'./../models/notification.model'
;
import
{
PositionModel
}
from
'../models/position.model'
;
import
{
ResponseModel
}
from
'./../models/base.model'
;
@
Injectable
({
providedIn
:
'root'
})
export
class
NotificationService
{
apiBaseUrl
=
"notifications/notifications"
;
constructor
(
private
http
:
HttpClient
,
private
translateService
:
TranslateService
)
{
}
/** ดึงตาม id */
getById
(
id
:
string
)
{
return
this
.
http
.
get
<
NotificationModel
>
(
`
${
this
.
apiBaseUrl
}
/
${
id
}
`
)
.
pipe
(
map
(
n
=>
new
NotificationModel
(
n
)));
}
/** ดึงทั้งหมด หรือกรอง project_id */
getList
(
projectId
?:
string
)
{
// ... ใช้ this.apiBaseUrl ตรง ๆ
return
this
.
http
.
get
<
NotificationModel
[]
>
(
this
.
apiBaseUrl
,)
.
pipe
(
map
(
arr
=>
arr
.
map
(
n
=>
new
NotificationModel
(
n
))));
}
/** ดึงแบบแบ่งหน้า */
getPage
(
body
:
{
page
:
number
;
size
:
number
},
projectId
?:
string
):
Observable
<
PageResponseModel
<
NotificationModel
>>
{
let
params
:
any
=
{
...
body
};
if
(
projectId
)
params
.
projectId
=
projectId
;
return
this
.
http
.
get
<
PageResponseModel
<
NotificationModel
>>
(
this
.
apiBaseUrl
,
{
params
})
.
pipe
(
map
(
p
=>
({
...
p
,
content
:
p
.
content
.
map
(
n
=>
new
NotificationModel
(
n
)),
}))
);
}
/** ดึงทุกหน้า (lazy-load ทุกหน้าเหมือนตัวอย่าง UserService) */
getAllPages
(
projectId
?:
string
)
{
const
first$
=
this
.
getPage
({
page
:
0
,
size
:
1
},
projectId
);
return
first$
.
pipe
(
switchMap
(
first
=>
{
const
size
=
500
;
const
pages
=
Math
.
ceil
(
first
.
totalElements
/
size
);
const
calls
:
Observable
<
PageResponseModel
<
NotificationModel
>>
[]
=
[];
for
(
let
page
=
0
;
page
<
pages
;
page
++
)
{
calls
.
push
(
this
.
getPage
({
page
,
size
},
projectId
));
}
return
forkJoin
(
calls
).
pipe
(
map
(
res
=>
res
.
flatMap
(
r
=>
r
.
content
))
);
})
);
}
/** ทำเครื่องหมายอ่านแล้ว */
markRead
(
id
:
string
)
{
return
this
.
http
.
put
<
ResponseModel
>
(
`
${
this
.
apiBaseUrl
}
/
${
id
}
/mark-read`
,
{}
);
}
/** นับจำนวนยังไม่อ่าน (optionally by project) */
getUnreadCount
(
projectId
?:
string
):
Observable
<
number
>
{
let
params
=
new
HttpParams
();
if
(
projectId
)
{
params
=
params
.
append
(
'projectId'
,
projectId
);
}
return
this
.
http
.
get
<
number
>
(
`
${
this
.
apiBaseUrl
}
/unread/count`
,
{
params
}).
pipe
(
catchError
(
error
=>
{
console
.
error
(
'Error fetching unread count:'
,
error
);
return
of
(
0
);
// คืนค่า 0 หากเกิด error
})
);
}
/** ลบ (ถ้าจำเป็น) */
delete
(
id
:
string
)
{
return
this
.
http
.
delete
<
ResponseModel
>
(
`
${
this
.
apiBaseUrl
}
/
${
id
}
`
);
}
}
Web-Manage/src/app/DPU/services/project-equipments.service.ts
View file @
f2f0f2ae
...
...
@@ -46,4 +46,5 @@ export class ProjectEquipmentService {
}
}
Web-Manage/src/app/authentication/login/login.component.html
View file @
f2f0f2ae
<div
style=
"background-color: rgb(1
74, 183, 165
); background-repeat: no-repeat; background-size: cover; background-attachment: fixed;"
style=
"background-color: rgb(1
50, 150, 150
); background-repeat: no-repeat; background-size: cover; background-attachment: fixed;"
class=
"flex justify-center authentication authentication-basic items-center h-full text-defaultsize text-defaulttextcolor"
>
<div
class=
"grid grid-cols-12"
>
<div
class=
"xxl:col-span-4 xl:col-span-4 lg:col-span-4 md:col-span-3 sm:col-span-2"
></div>
...
...
Web-Manage/src/app/shared/components/header/header.component.html
View file @
f2f0f2ae
...
...
@@ -60,9 +60,9 @@
<span
class=
"flex absolute h-5 w-5 -top-[0.25rem] end-0 -me-[0.6rem]"
>
<span
class=
"animate-slow-ping absolute inline-flex -top-[2px] -start-[2px] h-full w-full rounded-full bg-secondary/40 opacity-75"
></span>
<span
class=
"relative inline-flex justify-center items-center rounded-full h-[14.7px] w-[14px] bg-secondary text-[0.625rem] text-white"
id=
"notification-icon-badge"
>
{{ notificationCount }}
</span>
<span
*
ngIf=
"notificationCount > 0"
class=
"badge bg-danger rounded-pill"
>
{{ notificationCount }}
</span>
</span>
</button>
<div
...
...
@@ -104,107 +104,6 @@
</div>
</div>
</li>
<li
class=
"ti-dropdown-item dropdown-item !flex-none"
id=
"not2"
>
<div
class=
"flex items-start"
>
<div
class=
"pe-2"
>
<span
class=
"inline-flex text-secondary justify-center items-center !w-[2.5rem] !h-[2.5rem] !leading-[2.5rem] !text-[0.8rem] bg-secondary/10 rounded-[50%]"
><i
class=
"ti ti-discount-2 text-[1.125rem]"
></i></span>
</div>
<div
class=
"grow flex items-center justify-between"
>
<div>
<p
class=
"mb-0 text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50 text-[0.8125rem] font-semibold"
>
<a
routerLink=
"/pages/notifications"
>
Discount Available
</a></p>
<span
class=
"text-[#8c9097] dark:text-white/50 font-normal text-[0.75rem] header-notification-text"
>
Discount
Available On Selected Products
</span>
</div>
<div>
<a
aria-label=
"anchor"
(
click
)="
removeNotify
('
not2
')"
class=
"min-w-fit text-[#8c9097] dark:text-white/50 me-1 dropdown-item-close1"
><i
class=
"ti ti-x text-[1rem]"
></i></a>
</div>
</div>
</div>
</li>
<li
class=
"ti-dropdown-item dropdown-item"
id=
"not3"
>
<div
class=
"flex items-start"
>
<div
class=
"pe-2"
>
<span
class=
"inline-flex text-pink justify-center items-center !w-[2.5rem] !h-[2.5rem] !leading-[2.5rem] !text-[0.8rem] bg-pink/10 rounded-[50%]"
><i
class=
"ti ti-user-check text-[1.125rem]"
></i></span>
</div>
<div
class=
"grow flex items-center justify-between"
>
<div>
<p
class=
"mb-0 text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50 text-[0.8125rem] font-semibold"
>
<a
routerLink=
"/pages/notifications"
>
Account Has Been Verified
</a></p>
<span
class=
"text-[#8c9097] dark:text-white/50 font-normal text-[0.75rem] header-notification-text"
>
Your
Account Has
Been Verified Sucessfully
</span>
</div>
<div>
<a
aria-label=
"anchor"
(
click
)="
removeNotify
('
not3
')"
class=
"min-w-fit text-[#8c9097] dark:text-white/50 me-1 dropdown-item-close1"
><i
class=
"ti ti-x text-[1rem]"
></i></a>
</div>
</div>
</div>
</li>
<li
class=
"ti-dropdown-item dropdown-item"
id=
"not4"
>
<div
class=
"flex items-start"
>
<div
class=
"pe-2"
>
<span
class=
"inline-flex text-warning justify-center items-center !w-[2.5rem] !h-[2.5rem] !leading-[2.5rem] !text-[0.8rem] bg-warning/10 rounded-[50%]"
><i
class=
"ti ti-circle-check text-[1.125rem]"
></i></span>
</div>
<div
class=
"grow flex items-center justify-between"
>
<div>
<p
class=
"mb-0 text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50 text-[0.8125rem] font-semibold"
>
<a
routerLink=
"/pages/notifications"
>
Order Placed
<span
class=
"text-warning"
>
ID:
#1116773
</span></a></p>
<span
class=
"text-[#8c9097] dark:text-white/50 font-normal text-[0.75rem] header-notification-text"
>
Order
Placed
Successfully
</span>
</div>
<div>
<a
aria-label=
"anchor"
(
click
)="
removeNotify
('
not4
')"
class=
"min-w-fit text-[#8c9097] dark:text-white/50 me-1 dropdown-item-close1"
><i
class=
"ti ti-x text-[1rem]"
></i></a>
</div>
</div>
</div>
</li>
<li
class=
"ti-dropdown-item dropdown-item"
id=
"not5"
>
<div
class=
"flex items-start"
>
<div
class=
"pe-2"
>
<span
class=
"inline-flex text-success justify-center items-center !w-[2.5rem] !h-[2.5rem] !leading-[2.5rem] !text-[0.8rem] bg-success/10 rounded-[50%]"
><i
class=
"ti ti-clock text-[1.125rem]"
></i></span>
</div>
<div
class=
"grow flex items-center justify-between"
>
<div>
<p
class=
"mb-0 text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50 text-[0.8125rem] font-semibold"
>
<a
routerLink=
"/pages/notifications"
>
Order Delayed
<span
class=
"text-success"
>
ID:
7731116
</span></a></p>
<span
class=
"text-[#8c9097] dark:text-white/50 font-normal text-[0.75rem] header-notification-text"
>
Order
Delayed
Unfortunately
</span>
</div>
<div>
<a
aria-label=
"anchor"
(
click
)="
removeNotify
('
not5
')"
class=
"min-w-fit text-[#8c9097] dark:text-white/50 me-1 dropdown-item-close1"
><i
class=
"ti ti-x text-[1rem]"
></i></a>
</div>
</div>
</div>
</li>
</ul>
@if(!isNotifyEmpty){
...
...
Web-Manage/src/app/shared/components/header/header.component.ts
View file @
f2f0f2ae
...
...
@@ -4,6 +4,10 @@ import { TokenService } from '../../services/token.service';
import
{
TranslateService
}
from
'@ngx-translate/core'
;
import
{
UserModel
}
from
'../../user-auth.model'
;
import
{
UserProfileModel
}
from
'../../../DPU/models/user.model'
;
import
{
NotificationService
}
from
'../../../DPU/services/notification.service'
;
import
{
NotificationModel
}
from
'../../../DPU/models/notification.model'
;
import
{
interval
,
Subject
,
takeUntil
}
from
'rxjs'
;
interface
Item
{
id
:
number
;
name
:
string
;
...
...
@@ -20,14 +24,16 @@ interface Item {
export
class
HeaderComponent
{
userModel
:
UserProfileModel
=
new
UserProfileModel
(
this
.
tokenService
.
getUser
().
member
,
this
.
translate
)
adminRole
=
false
notificationCount
=
0
;
private
destroy$
=
new
Subject
<
void
>
();
cartItemCount
:
number
=
5
;
notificationCount
:
number
=
5
;
public
isCollapsed
=
true
;
public
selectedLanguage
=
""
;
constructor
(
public
navServices
:
NavService
,
constructor
(
p
rivate
notificationService
:
NotificationService
,
p
ublic
navServices
:
NavService
,
private
elementRef
:
ElementRef
,
private
renderer
:
Renderer2
,
private
tokenService
:
TokenService
,
private
translate
:
TranslateService
)
{
private
translate
:
TranslateService
,
private
notificationSvc
:
NotificationService
)
{
this
.
translate
.
use
(
sessionStorage
.
getItem
(
"Lang"
)
!=
null
...
...
@@ -149,6 +155,43 @@ export class HeaderComponent {
this
.
navServices
.
items
.
subscribe
((
menuItems
)
=>
{
this
.
items
=
menuItems
;
});
this
.
adminRole
=
this
.
tokenService
.
getUser
().
member
.
role
===
99
;
this
.
navServices
.
items
.
subscribe
(
m
=>
(
this
.
items
=
m
));
this
.
loadUnreadCount
();
this
.
setupAutoRefresh
();
}
ngOnDestroy
():
void
{
this
.
destroy$
.
next
();
this
.
destroy$
.
complete
();
}
// โหลดจำนวนแจ้งเตือนที่ยังไม่อ่าน
loadUnreadCount
():
void
{
this
.
notificationService
.
getUnreadCount
().
subscribe
(
count
=>
this
.
notificationCount
=
count
);
}
// รีเฟรชอัตโนมัติทุก 1 นาที
private
setupAutoRefresh
():
void
{
interval
(
60000
).
pipe
(
takeUntil
(
this
.
destroy$
)
).
subscribe
(()
=>
{
this
.
loadUnreadCount
();
});
}
// เมื่อผู้ใช้เปิดอ่านการแจ้งเตือน
markAsRead
(
notificationId
:
string
):
void
{
this
.
notificationService
.
markRead
(
notificationId
).
subscribe
({
next
:
()
=>
{
if
(
this
.
notificationCount
>
0
)
{
this
.
notificationCount
--
;
}
},
error
:
(
err
)
=>
console
.
error
(
'Failed to mark as read'
,
err
)
});
}
Search
(
searchText
:
string
)
{
...
...
Web-Manage/src/app/shared/components/sidebar/sidebar.component.html
View file @
f2f0f2ae
<aside
class=
"app-sidebar"
id=
"sidebar"
[
ngClass
]="{
'
sticky-pin
'
:
scrolled
}"
>
<!-- Start::main-sidebar-header -->
<div
class=
"main-sidebar-header
"
style=
"background-color: white !important;"
>
<div
class=
"main-sidebar-header
"
style=
"background-color: rgb(237, 237, 237) "
>
<a
class=
"header-logo"
>
<!-- <img src="./assets/images/brand-logos/logo.png" alt="logo" width="100%">test -->
...
...
@@ -12,10 +12,10 @@
</div>
<div>
<ngx-simplebar
[
options
]="
options
"
class=
"main-sidebar"
id=
"sidebar-scroll"
>
<nav
class=
"main-menu-container nav nav-pills flex-column sub-open"
>
<nav
class=
"main-menu-container nav nav-pills flex-column sub-open"
>
<div
class=
"slide-left"
id=
"slide-left"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
fill=
"#7b8
191
"
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
fill=
"#7b8"
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
>
<path
d=
"M13.293 6.293 7.586 12l5.707 5.707 1.414-1.414L10.414 12l4.293-4.293z"
></path>
</svg>
</div>
...
...
Web-Manage/src/assets/i18n/th.json
View file @
f2f0f2ae
...
...
@@ -29,9 +29,9 @@
"Status"
:
"สถานะ"
,
"Gender"
:
"เพศ"
,
"Admin-System"
:
"ผู้ดูแลระบบ"
,
"Admin-Company"
:
"ผู้
ดูแลบริษัท
"
,
"Admin-Company"
:
"ผู้
จัดการโครงการ
"
,
"Amount"
:
"จำนวน"
,
"User"
:
"
ผู้ใช้งาน
"
,
"User"
:
"
พนักงานบริษัท
"
,
"User Group"
:
"กลุ่มผู้ใช้งาน"
,
"User Role"
:
"บทบาทผู้ใช้งาน"
,
"User Setting"
:
"กำหนดผู้ใช้งาน"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment