Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
portal-apps-manage
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
angular
portal-apps-manage
Commits
27f02f55
Commit
27f02f55
authored
Sep 14, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
portal
parent
8b2e4a55
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
13 additions
and
2738 deletions
+13
-2738
mock-data.service.ts
src/app/portal-manage/common/mock-data.service.ts
+0
-48
company-emp.component.css
.../company-management/company-emp/company-emp.component.css
+0
-3
company-emp.component.html
...company-management/company-emp/company-emp.component.html
+0
-370
company-emp.component.ts
...e/company-management/company-emp/company-emp.component.ts
+0
-379
company-info.component.css
...ompany-management/company-info/company-info.component.css
+0
-7
company-info.component.html
...mpany-management/company-info/company-info.component.html
+0
-128
company-info.component.ts
...company-management/company-info/company-info.component.ts
+0
-168
company-location.component.css
...anagement/company-location/company-location.component.css
+0
-7
company-location.component.html
...nagement/company-location/company-location.component.html
+0
-288
company-location.component.ts
...management/company-location/company-location.component.ts
+0
-261
company-management.component.css
...anage/company-management/company-management.component.css
+0
-0
company-management.component.html
...nage/company-management/company-management.component.html
+0
-3
company-management.component.ts
...manage/company-management/company-management.component.ts
+0
-34
company-management.module.ts
...al-manage/company-management/company-management.module.ts
+0
-28
enroll-face.component.html
...company-management/enroll-face/enroll-face.component.html
+0
-12
enroll-face.component.scss
...company-management/enroll-face/enroll-face.component.scss
+0
-0
enroll-face.component.ts
...e/company-management/enroll-face/enroll-face.component.ts
+0
-259
home-installer.component.css
...ny-management/home-installer/home-installer.component.css
+0
-0
home-installer.component.html
...y-management/home-installer/home-installer.component.html
+0
-0
home-installer.component.spec.ts
...anagement/home-installer/home-installer.component.spec.ts
+0
-28
home-installer.component.ts
...any-management/home-installer/home-installer.component.ts
+0
-31
timestamp-log.component.css
...pany-management/timestamp-log/timestamp-log.component.css
+0
-7
timestamp-log.component.html
...any-management/timestamp-log/timestamp-log.component.html
+0
-234
timestamp-log.component.spec.ts
...-management/timestamp-log/timestamp-log.component.spec.ts
+0
-28
timestamp-log.component.ts
...mpany-management/timestamp-log/timestamp-log.component.ts
+0
-265
warning-timetamp.component.css
...anagement/warning-timetamp/warning-timetamp.component.css
+0
-0
warning-timetamp.component.html
...nagement/warning-timetamp/warning-timetamp.component.html
+0
-3
warning-timetamp.component.spec.ts
...ement/warning-timetamp/warning-timetamp.component.spec.ts
+0
-28
warning-timetamp.component.ts
...management/warning-timetamp/warning-timetamp.component.ts
+0
-16
home.component.ts
src/app/portal-manage/home/home.component.ts
+4
-68
portal-manage.routes.ts
src/app/portal-manage/portal-manage.routes.ts
+0
-7
widget-stock.component.html
...pp/portal-manage/widget-stock/widget-stock.component.html
+0
-0
widget-stock.component.scss
...pp/portal-manage/widget-stock/widget-stock.component.scss
+0
-1
widget-stock.component.ts
src/app/portal-manage/widget-stock/widget-stock.component.ts
+0
-25
header.component.html
src/app/shared/components/header/header.component.html
+9
-0
content.routes.ts
src/app/shared/routes/content.routes.ts
+0
-2
No files found.
src/app/portal-manage/common/mock-data.service.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
Injectable
}
from
'@angular/core'
;
@
Injectable
({
providedIn
:
'root'
})
export
class
MockDataService
{
constructor
()
{
}
getKpiData
(
kpiName
:
string
)
{
const
kpiData
:
{
[
key
:
string
]:
{
value
:
number
,
trend
:
'up'
|
'down'
|
'flat'
,
percentage
:
number
}
}
=
{
'New Hires'
:
{
value
:
12
,
trend
:
'up'
,
percentage
:
15
},
'Turnover Rate'
:
{
value
:
4
,
trend
:
'down'
,
percentage
:
10
},
'Employee Satisfaction'
:
{
value
:
4.5
,
trend
:
'up'
,
percentage
:
5
},
'Projects Completed'
:
{
value
:
25
,
trend
:
'up'
,
percentage
:
20
}
};
return
kpiData
[
kpiName
]
||
{
value
:
0
,
trend
:
'flat'
,
percentage
:
0
};
}
getChartData
()
{
return
{
categories
:
[
'Jan'
,
'Feb'
,
'Mar'
,
'Apr'
,
'May'
,
'Jun'
],
series
:
[
{
name
:
'Hiring'
,
data
:
[
5
,
8
,
12
,
10
,
15
,
18
]
},
{
name
:
'Resignations'
,
data
:
[
2
,
3
,
5
,
4
,
6
,
5
]
}
]
};
}
getWelcomeMessage
(
userName
:
string
=
'Admin'
)
{
return
`Welcome back,
${
userName
}
!`
;
}
getQuickLinks
()
{
return
[
{
name
:
'Company Portal'
,
url
:
'#'
},
{
name
:
'HR Handbook'
,
url
:
'#'
},
{
name
:
'Submit IT Ticket'
,
url
:
'#'
},
{
name
:
'View Paystubs'
,
url
:
'#'
}
];
}
}
src/app/portal-manage/company-management/company-emp/company-emp.component.css
deleted
100644 → 0
View file @
8b2e4a55
:host
{
display
:
block
;
}
src/app/portal-manage/company-management/company-emp/company-emp.component.html
deleted
100644 → 0
View file @
8b2e4a55
<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"
>
{{ 'All List' | translate}}
<span
class=
"badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle"
>
{{itemsList.length}}
</span>
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
new
()"
data-hs-overlay=
"#modal-detail"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'เพิ่ม' |
translate}}
</a>
<div>
<input
[(
ngModel
)]='
searchTerm
'
class=
"form-control form-control"
type=
"text"
placeholder=
"{{ 'ค้นหาข้อมูลพนักงาน' | translate}}"
aria-label=
".form-control-sm example"
>
</div>
<!-- <a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Posted Date</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Status</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Department</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Job Type</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul> -->
</div>
</div>
</div>
</div>
@for(item of filterList;track filterList){
<div
class=
"xxl:col-span-4 xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-12 col-span-12"
>
<div
class=
"box team-member-card"
>
<div
class=
"teammember-cover-image mt-1"
>
<span
class=
"avatar avatar-xl avatar-rounded"
>
<img
[
src
]="
item
.
member
.
getPicture
()"
alt=
""
>
</span>
</div>
<div
class=
"box-body !p-0"
>
<div
class=
"flex flex-wrap align-item-center sm:mt-0 mt-[3rem] justify-between border-b border-dashed dark:border-defaultborder/10 p-4"
>
<div
class=
"team-member-details flex-grow"
>
<p
class=
"mb-0 font-semibold text-[1rem] text-truncate"
>
<a
href=
"javascript:void(0);"
>
{{item.member.firstName+ ' ' +item.member.lastName}}
</a>
</p>
<p
class=
"mb-0 text-[0.75rem] text-[#8c9097] dark:text-white/50 text-truncate"
>
{{item.member.email}}
</p>
</div>
</div>
<div
class=
"team-member-stats sm:flex items-center justify-evenly"
>
<div
class=
"text-center p-4 w-full"
>
<p
class=
"font-semibold mb-0"
>
รหัสพนักงาน
</p>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.75rem]"
>
{{item.employeeId}}
</span>
</div>
<div
class=
"text-center p-4 w-full"
>
<p
class=
"font-semibold mb-0"
>
แผนก
</p>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.75rem]"
>
{{item.position.thName}}
</span>
</div>
<div
class=
"text-center p-4 w-full"
>
<p
class=
"font-semibold mb-0"
>
ตำแหน่ง
</p>
<span
class=
"text-[#8c9097] dark:text-white/50 text-[0.75rem]"
>
{{item.department.thName}}
</span>
</div>
</div>
</div>
<div
class=
"box-footer border-block-start-dashed dark:border-defaultborder/10 text-center"
>
<div
class=
"btn-list"
>
<div
class=
"btn-list"
>
<button
type=
"button"
aria-label=
"button"
data-hs-overlay=
"#modal-detail"
(
click
)="
view
(
item
)"
class=
"ti-btn ti-btn-sm ti-btn-primary me-[0.375rem]"
><i
class=
"ri-edit-line"
></i></button>
<button
routerLink=
"/company/timestamp-log/{{item.company_employeeId}}"
routerLinkActive=
"active"
type=
"button"
aria-label=
"button"
class=
"ti-btn ti-btn-sm ti-btn-secondary !me-[0.375rem]"
>
<i
class=
"ri-time-line"
></i>
</button>
<button
data-hs-overlay=
"#modal-face"
(
click
)="
view
(
item
)"
type=
"button"
aria-label=
"button"
class=
"ti-btn ti-btn-sm ti-btn-warning me-[0.375rem]"
>
<i
class=
"ri-account-circle-line"
></i>
</button>
<button
(
click
)="
delete
(
item
)"
type=
"button"
aria-label=
"button"
class=
"ti-btn ti-btn-sm ti-btn-danger me-0"
><i
class=
"ri-delete-bin-line"
></i></button>
</div>
</div>
</div>
</div>
</div>
}
</div>
<!-- <nav aria-label="Page navigation" class="mb-4">
<ul class="ti-pagination !justify-end py-[0.375rem] px-3 text-[1rem] flex flex-row">
<li class="page-item disabled"><a class="page-link py-[0.375rem] px-3" href="javascript:void(0);">Previous</a></li>
<li class="page-item"><a class="page-link py-[0.375rem] px-3" href="javascript:void(0);">1</a></li>
<li class="page-item"><a class="page-link py-[0.375rem] px-3" href="javascript:void(0);">2</a></li>
<li class="page-item"><a class="page-link py-[0.375rem] px-3" href="javascript:void(0);">Next</a></li>
</ul>
</nav> -->
<!-- Start:: New Deal -->
<div
id=
"modal-detail"
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"
id=
"mail-ComposeLabel"
>
ข้อมูลพนักงาน
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay=
"#modal-detail"
>
<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"
>
<div
class=
"mb-0 text-center"
>
<span
class=
"avatar avatar-xxl avatar-rounded"
>
<img
[
src
]="
selectModel
.
getPicture
()"
alt=
""
id=
"profile-img"
>
<span
class=
"badge rounded-full bg-primary avatar-badge"
>
<input
ng2FileSelect
[
uploader
]="
uploaderProfile
"
type=
"file"
name=
"photo"
class=
"absolute w-full h-full opacity-[0]"
id=
"profile-change"
>
<i
class=
"fe fe-camera text-[.625rem]"
></i>
</span>
</span>
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
ชื่อ
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-name"
placeholder=
"ชื่อ"
[(
ngModel
)]="
selectModel
.
member
.
firstName
"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-lead-score"
class=
"form-label"
>
นามสกุล
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-lead-score"
placeholder=
"นามสกุล"
[(
ngModel
)]="
selectModel
.
member
.
lastName
"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"company-name"
class=
"form-label"
>
อีเมล
</label>
<input
type=
"text"
class=
"form-control"
id=
"company-name"
placeholder=
"อีเมล"
[(
ngModel
)]="
selectModel
.
member
.
email
"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
วันเริ่มงาน
</label>
<div
class=
"form-group"
>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"endDate"
placeholder=
"Choose date with time"
mwlFlatpickr
[(
ngModel
)]="
selectModel
.
startDate
"
[
enableTime
]="
true
"
[
convertModelValue
]="
true
"
[
dateFormat
]="'
Y-m-d
H:i
'"
>
</div>
</div>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-lead-score"
class=
"form-label"
>
รหัสพนักงาน
</label>
<input
type=
"text"
class=
"form-control"
id=
"deal-lead-score"
placeholder=
"นามสกุล"
[(
ngModel
)]="
selectModel
.
employeeId
"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
หัวหน้างาน
</label>
<ng-select
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
""
[(
ngModel
)]="
selectModel
.
bossId
"
>
@for(item of itemsList;track itemsList){
<ng-option
[
value
]="
item
.
member
.
memberId
"
>
{{item.member.firstName+"
"+item.member.lastName}}
</ng-option>
}
</ng-select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
แผนก
</label>
<!-- <ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModel.department">
@for(item of departmentList;track departmentList){
<ng-option [value]="item">{{item.thName}}</ng-option>
}
</ng-select> -->
<ng-select
#
select
[
items
]="
departmentList
"
[
searchable
]="
false
"
[(
ngModel
)]="
selectModel
.
department
"
bindLabel=
"thName"
>
<ng-template
ng-header-tmp
>
<input
style=
"width: 100%; line-height: 24px"
type=
"text"
(
input
)="
select
.
filter
($
any
($
event
.
target
).
value
)"
/>
</ng-template>
</ng-select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
ตำแหน่ง
</label>
<!-- <ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModel.position.positionId">
@for(item of positionList;track positionList){
<ng-option [value]="item">{{item.thName}}</ng-option>
}
</ng-select> -->
<ng-select
#
select2
[
items
]="
positionList
"
[
searchable
]="
false
"
[(
ngModel
)]="
selectModel
.
position
"
bindLabel=
"thName"
>
<ng-template
ng-header-tmp
>
<input
style=
"width: 100%; line-height: 24px"
type=
"text"
(
input
)="
select2
.
filter
($
any
($
event
.
target
).
value
)"
/>
</ng-template>
</ng-select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
ประเภท
</label>
<ng-select
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
""
[(
ngModel
)]="
selectModel
.
empType
"
>
<ng-option
[
value
]="
0
"
>
รายวัน
</ng-option>
<ng-option
[
value
]="
1
"
>
รายเดือน
</ng-option>
</ng-select>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
เงินเดือน
</label>
<input
type=
"text"
class=
"form-control"
id=
"company-name"
placeholder=
"เงินเดือน"
[(
ngModel
)]="
selectModel
.
salary
"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"deal-name"
class=
"form-label"
>
สิทธิ์การใช้งาน
</label>
<ng-select
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
""
[(
ngModel
)]="
selectModel
.
companyRoleType
"
>
<ng-option
[
value
]="
0
"
>
พนักงาน
</ng-option>
<ng-option
[
value
]="
1
"
>
ผู้ดูแลบริษัท
</ng-option>
</ng-select>
</div>
</div>
</div>
<div
class=
"ti-modal-footer"
>
<button
#
closeModal
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay=
"#modal-detail"
>
ยกเลิก
</button>
<button
type=
"button"
class=
"ti-btn bg-primary text-white !font-medium"
(
click
)="
save
()"
>
บันทึก
</button>
</div>
</div>
</div>
</div>
<div
id=
"modal-face"
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"
id=
"mail-ComposeLabel"
>
ข้อมูลพนักงาน
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay=
"#modal-face"
>
<span
class=
"sr-only"
>
Close
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body"
>
<div
class=
"flex flex-wrap align-item-center sm:mt-0 mt-[3rem] justify-between border-b border-dashed dark:border-defaultborder/10 p-4"
>
<div
class=
"team-member-details flex-grow"
>
<video
#
video
width=
"640"
height=
"480"
style=
"width: 100%; object-fit: cover;"
autoplay
(
loadedmetadata
)="
detectFace
()"
>
</video>
<!-- Canvas element -->
<canvas
#
canvas
width=
"640"
height=
"480"
hidden
style=
"position: absolute; width: 100%; height: 100%; object-fit: cover;"
>
</canvas>
</div>
</div>
</div>
<div
class=
"ti-modal-footer"
>
<button
#
closeModalFace
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay=
"#modal-face"
>
ยกเลิก
</button>
<button
*
ngIf=
"checkMatch"
type=
"button"
class=
"ti-btn bg-primary text-white !font-medium"
(
click
)="
captureImage
()"
>
บันทึกใบหน้า
</button>
</div>
</div>
</div>
</div>
<!-- <div id="modal-detail-edit" class="hs-overlay hidden ti-modal" *ngIf="selectModelEdit">
<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-detail">
<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">
<div class="mb-0 text-center">
<span class="avatar avatar-xxl avatar-rounded">
<img [src]="'./assets/images/faces/1.jpg'" alt="" id="profile-img">
<span class="badge rounded-full bg-primary avatar-badge">
<input type="file" name="photo" class="absolute w-full h-full opacity-[0]" id="profile-change">
<i class="fe fe-camera text-[.625rem]"></i>
</span>
</span>
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-name" class="form-label">ชื่อ</label>
<input type="text" class="form-control" id="deal-name" placeholder="ชื่อ"
[(ngModel)]="selectModelEdit.member.firstName">
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-lead-score" class="form-label">นามสกุล</label>
<input type="text" class="form-control" id="deal-lead-score" placeholder="นามสกุล"
[(ngModel)]="selectModelEdit.member.lastName">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="company-name" class="form-label">อีเมล</label>
<input type="text" class="form-control" id="company-name" placeholder="อีเมล"
[(ngModel)]="selectModelEdit.member.email">
</div>
<div class="xl:col-span-12 col-span-12">
<label class="form-label">วันเริ่มงาน</label>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="endDate" placeholder="Choose date with time" mwlFlatpickr [(ngModel)]="selectModelEdit.startDate"
[enableTime]="true" [convertModelValue]="true" [dateFormat]="'Y-m-d H:i'">
</div>
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-name" class="form-label">แผนก</label>
<ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModelEdit.department.departmentId">
@for(item of departmentList;track departmentList){
<ng-option [value]="item.departmentId">{{item.thName}}</ng-option>
}
</ng-select>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-name" class="form-label">ตำแหน่ง</label>
<ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModelEdit.position.positionId">
@for(item of positionList;track positionList){
<ng-option [value]="item.positionId">{{item.thName}}</ng-option>
}
</ng-select>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-name" class="form-label">ประเภท</label>
<ng-select name="choices-multiple-remove-button1" id="choices-multiple-remove-button1" placeholder=""
[(ngModel)]="selectModelEdit.empType">
<ng-option [value]="0">รายวัน</ng-option>
<ng-option [value]="1">รายเดือน</ng-option>
</ng-select>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="deal-name" class="form-label">เงินเดือน</label>
<input type="text" class="form-control" id="company-name" placeholder="เงินเดือน" [(ngModel)]="selectModelEdit.salary">
</div>
</div>
</div>
<div class="ti-modal-footer">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay="#modal-detail-edit">
ยกเลิก
</button>
<button type="button" class="ti-btn bg-primary text-white !font-medium" (click)="updateEmp()">บันทึก</button>
</div>
</div>
</div>
</div> -->
src/app/portal-manage/company-management/company-emp/company-emp.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
CommonModule
}
from
"@angular/common"
;
import
{
ChangeDetectionStrategy
,
Component
,
ElementRef
,
ViewChild
}
from
'@angular/core'
;
import
{
MaterialModuleModule
}
from
"../../../material-module/material-module.module"
;
import
{
RouterModule
}
from
"@angular/router"
;
import
{
NgSelectModule
}
from
"@ng-select/ng-select"
;
import
{
SharedModule
}
from
"../../../shared/shared.module"
;
import
{
TranslateModule
,
TranslateService
}
from
"@ngx-translate/core"
;
import
{
FlatpickrDefaults
,
FlatpickrModule
}
from
"angularx-flatpickr"
;
import
{
MatDatepickerModule
}
from
"@angular/material/datepicker"
;
import
{
EmployeeModel
}
from
"../../models/employee.model"
;
import
{
EmployeeService
}
from
"../../services/employee.service"
;
import
{
TokenService
}
from
"../../../shared/services/token.service"
;
import
swal
from
'sweetalert'
;
import
{
DepartmentService
}
from
"../../services/department.service"
;
import
{
PositionService
}
from
"../../services/position.service"
;
import
{
DepartmentModel
}
from
"../../models/department.model"
;
import
{
PositionModel
}
from
"../../models/position.model"
;
import
{
FormsModule
}
from
"@angular/forms"
;
import
{
FileUploadModule
}
from
'ng2-file-upload'
;
import
{
FileItem
,
FileUploader
,
ParsedResponseHeaders
}
from
"ng2-file-upload"
;
import
{
environment
}
from
"../../../../environments/environment"
;
import
{
HttpClient
}
from
"@angular/common/http"
;
import
*
as
faceapi
from
'face-api.js'
;
@
Component
({
selector
:
'app-company-emp'
,
standalone
:
true
,
imports
:
[
SharedModule
,
NgSelectModule
,
RouterModule
,
MaterialModuleModule
,
TranslateModule
,
FlatpickrModule
,
MatDatepickerModule
,
FormsModule
,
CommonModule
,
FileUploadModule
],
providers
:
[
FlatpickrDefaults
],
templateUrl
:
'./company-emp.component.html'
,
styleUrl
:
'./company-emp.component.css'
,
})
export
class
CompanyEmpComponent
{
@
ViewChild
(
'closeModal'
)
public
childModal
?:
ElementRef
;
@
ViewChild
(
'closeModalFace'
)
public
childModalFace
?:
ElementRef
;
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
allSelected
=
false
;
someSelected
=
false
;
uploaderProfile
:
FileUploader
|
undefined
;
uploadErrorMsg
:
string
=
""
;
itemsList
:
EmployeeModel
[]
=
[]
filterList
:
EmployeeModel
[]
=
[]
selectModel
:
EmployeeModel
=
new
EmployeeModel
()
selectedItems
=
new
Map
<
string
,
boolean
>
();
departmentList
:
DepartmentModel
[]
=
[]
positionList
:
PositionModel
[]
=
[]
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
()
}
}
companyId
=
""
_searchTerm
=
""
;
isEdit
=
false
;
constructor
(
private
http
:
HttpClient
,
private
employeeService
:
EmployeeService
,
public
translate
:
TranslateService
,
private
departmentService
:
DepartmentService
,
private
positionService
:
PositionService
,
private
tokenService
:
TokenService
)
{
this
.
uploadConfig
()
this
.
companyId
=
this
.
tokenService
.
getSelectCompany
().
companyId
;
}
@
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
initFace
()
{
// โหลดโมเดล Face Detection ของ face-api.js
faceapi
.
nets
.
tinyFaceDetector
.
loadFromUri
(
'/assets/models/tiny_face_detector'
);
faceapi
.
nets
.
faceLandmark68Net
.
loadFromUri
(
'/assets/models/face_landmark_68'
);
faceapi
.
nets
.
faceRecognitionNet
.
loadFromUri
(
'/assets/models/face_recognition'
);
faceapi
.
nets
.
faceExpressionNet
.
loadFromUri
(
'/assets/models/face_expression'
);
// เปิดกล้อง
this
.
startVideo
();
}
startVideo
():
void
{
console
.
log
(
"test"
)
navigator
.
mediaDevices
.
getUserMedia
({
video
:
true
})
.
then
(
stream
=>
{
this
.
video
.
nativeElement
.
srcObject
=
stream
;
})
.
catch
(
err
=>
{
console
.
error
(
'Error accessing camera: '
,
err
);
});
}
// ตรวจจับใบหน้าและวาดกรอบครอบใบหน้า
async
detectFace
()
{
const
videoEl
=
this
.
video
.
nativeElement
;
const
displaySize
=
{
width
:
videoEl
.
width
,
height
:
videoEl
.
height
};
faceapi
.
matchDimensions
(
this
.
canvas
.
nativeElement
,
displaySize
);
setInterval
(
async
()
=>
{
const
detections
=
await
faceapi
.
detectAllFaces
(
videoEl
,
new
faceapi
.
TinyFaceDetectorOptions
()).
withFaceLandmarks
().
withFaceExpressions
();
const
resizedDetections
=
faceapi
.
resizeResults
(
detections
,
displaySize
);
// Clear the canvas
this
.
canvas
.
nativeElement
.
getContext
(
'2d'
).
clearRect
(
0
,
0
,
displaySize
.
width
,
displaySize
.
height
);
// Draw detections
faceapi
.
draw
.
drawDetections
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
faceapi
.
draw
.
drawFaceExpressions
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
faceapi
.
draw
.
drawFaceLandmarks
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
// Check if at least one face is detected
this
.
isFaceDetected
=
detections
.
length
>
0
;
this
.
checkMatch
=
this
.
isFaceDetected
;
},
500
);
}
// @ViewChild('video') videoElement!: ElementRef;
// @ViewChild('canvas') canvasElement!: ElementRef;
// capturedImage: string | null = null;
// uploadStatus: string = '';
// constructor(private http: HttpClient) {}
// ngOnInit(): void {
// this.startCamera();
// }
// // เริ่มการทำงานของกล้อง
// startCamera(): void {
// navigator.mediaDevices.getUserMedia({ video: true })
// .then(stream => {
// this.videoElement.nativeElement.srcObject = stream;
// })
// .catch(err => {
// console.error('Error accessing camera: ', err);
// });
// }
// // แคปเจอร์ภาพจากกล้อง
captureImage
():
void
{
const
video
=
this
.
video
.
nativeElement
;
const
canvas
=
this
.
canvas
.
nativeElement
;
const
context
=
canvas
.
getContext
(
'2d'
);
// วาดภาพจาก video ลงใน canvas
context
.
drawImage
(
video
,
0
,
0
,
canvas
.
width
,
canvas
.
height
);
// แปลงภาพใน canvas เป็น base64
this
.
capturedImage
=
canvas
.
toDataURL
(
'image/jpeg'
);
this
.
uploadImage
()
}
// // อัปโหลดภาพที่แคปเจอร์แล้ว
uploadImage
():
void
{
if
(
this
.
capturedImage
)
{
// แปลง Base64 เป็นไฟล์
const
file
=
this
.
dataURLtoFile
(
this
.
capturedImage
,
'face.jpg'
);
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
// ส่งคำร้อง HTTP POST ไปยัง backend
this
.
http
.
post
(
environment
.
baseUrl
+
`/face/members/
${
this
.
selectModel
.
member
.
memberId
}
/add-face`
,
formData
).
subscribe
({
next
:
(
response
:
any
)
=>
{
this
.
uploadStatus
=
'Face uploaded successfully!'
;
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
},
error
:
(
error
)
=>
{
this
.
uploadStatus
=
'Error uploading face!'
;
console
.
error
(
'Error:'
,
error
);
}
});
}
}
// // แปลง Base64 เป็นไฟล์ (Blob)
dataURLtoFile
(
dataurl
:
string
,
filename
:
string
):
File
{
const
arr
:
any
=
dataurl
.
split
(
','
);
const
mime
=
arr
[
0
].
match
(
/:
(
.*
?)
;/
)[
1
];
const
bstr
=
atob
(
arr
[
1
]);
let
n
=
bstr
.
length
;
const
u8arr
=
new
Uint8Array
(
n
);
while
(
n
--
)
{
u8arr
[
n
]
=
bstr
.
charCodeAt
(
n
);
}
return
new
File
([
u8arr
],
filename
,
{
type
:
mime
});
}
uploadConfig
()
{
this
.
uploaderProfile
=
new
FileUploader
({
url
:
environment
.
baseUrl
+
"/api/upload-image"
,
isHTML5
:
true
,
authToken
:
this
.
tokenService
.
getToken
()
!
,
});
this
.
uploaderProfile
.
onAfterAddingFile
=
(
fileItem
:
FileItem
)
=>
{
fileItem
.
withCredentials
=
false
;
this
.
uploadErrorMsg
=
""
;
while
(
this
.
uploaderProfile
!
.
queue
.
length
>
1
)
{
this
.
uploaderProfile
!
.
queue
[
0
].
remove
();
}
if
(
fileItem
.
file
.
size
>
5000000
)
{
this
.
uploadErrorMsg
=
"maximum file size 5mb."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
fileItem
.
isCancel
=
true
;
return
;
}
if
(
fileItem
.
file
.
type
!
.
indexOf
(
"image"
)
===
-
1
)
{
this
.
uploadErrorMsg
=
"please upload image only."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
fileItem
.
isCancel
=
true
;
return
;
}
fileItem
.
upload
();
};
this
.
uploaderProfile
.
onCompleteItem
=
(
item
:
FileItem
,
response
:
string
,
status
:
number
,
headers
:
ParsedResponseHeaders
)
=>
{
if
(
item
.
isSuccess
)
{
const
res
=
JSON
.
parse
(
response
);
console
.
log
(
"res"
,
res
);
this
.
selectModel
.
member
.
picture
=
res
.
filename
swal
(
res
.
message
,
"บันทึกสำเร็จ"
,
"success"
);
}
else
{
this
.
uploadErrorMsg
=
"cannot upload file."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
}
};
}
ngOnInit
():
void
{
this
.
initFace
()
this
.
getDepartment
()
this
.
getPosition
()
this
.
employeeService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
itemsList
=
result
this
.
updatePagedItems
()
})
}
getDepartment
()
{
this
.
departmentService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
departmentList
=
result
})
}
getPosition
()
{
this
.
positionService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
positionList
=
result
})
}
filter
(
v
:
string
)
{
this
.
pageIndex
=
0
;
return
this
.
itemsList
?.
filter
(
(
x
)
=>
x
.
company_employeeId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
employeeId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getFullname
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getType
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getRole
()?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
position
.
getName
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
department
.
getName
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
delete
(
item
:
EmployeeModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"You won't be able to revert this!"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"Cancel"
,
"Yes,Delete it!"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
employeeService
.
delete
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
()
})
}
});
}
new
()
{
this
.
isEdit
=
false
this
.
selectModel
=
new
EmployeeModel
()
}
view
(
item
:
EmployeeModel
)
{
console
.
log
(
item
)
this
.
isEdit
=
true
;
this
.
selectModel
=
item
}
save
()
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
if
(
!
this
.
isEdit
)
{
this
.
selectModel
.
companyRoleType
=
0
this
.
employeeService
.
save
(
this
.
selectModel
,
this
.
companyId
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
else
{
this
.
employeeService
.
update
(
this
.
selectModel
,
this
.
companyId
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
// this.selectModel.member.role = 0
}
});
}
updateEmp
()
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
employeeService
.
save
(
this
.
selectModel
,
this
.
companyId
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
ngOnInit
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
});
}
// filterEmp(empId: string) {
// this.selectModel.supervisor = this.itemsList.filter(e => e.employeeId == empId)[0]
// }
updatePagedItems
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
// this.filterList = this.itemsList.slice(startIndex, endIndex);
this
.
filterList
=
this
.
itemsList
}
}
src/app/portal-manage/company-management/company-info/company-info.component.css
deleted
100644 → 0
View file @
8b2e4a55
:host
{
display
:
block
;
}
.map-container
{
width
:
100%
!important
}
src/app/portal-manage/company-management/company-info/company-info.component.html
deleted
100644 → 0
View file @
8b2e4a55
<app-page-header
[
title
]="'ข้อมูลบริษัท'"
[
activeTitle
]="'จัดการบริษัท'"
[
title1
]="'ข้อมูลบริษัท'"
></app-page-header>
<!-- Start::row-1 -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-8 col-span-12"
>
<div
class=
"box custom-box"
>
<div
class=
"box-header justify-between flex"
>
<div
class=
"box-title"
>
ข้อมูลบริษัท
</div>
<div>
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"sm:p-4 p-0"
>
<h6
class=
"font-semibold mb-4 text-[1rem]"
>
รูปภาพ :
</h6>
<div
class=
"mb-6 sm:flex items-center"
>
<div
class=
"mb-0 me-[3rem]"
>
<span
class=
"avatar avatar-xxl avatar-rounded"
>
<img
[
src
]="
companyModel
.
getPicture
()"
alt=
""
id=
"profile-img"
>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
class=
"badge rounded-full bg-primary avatar-badge"
>
<input
ng2FileSelect
[
uploader
]="
uploaderProfile
"
type=
"file"
name=
"photo"
class=
"absolute w-full h-full opacity-0"
id=
"profile-image"
>
<i
class=
"fe fe-camera !text-[0.65rem]"
></i>
</a>
</span>
</div>
<!-- <div class="inline-flex">
<button type="button" class="ti-btn bg-primary text-white !rounded-e-none !font-medium">แก้ไข</button>
<button type="button" class="ti-btn ti-btn-light !font-medium !rounded-s-none">ลบ</button>
</div> -->
</div>
<div
class=
"sm:grid grid-cols-12 gap-6 mb-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"first-name"
class=
"form-label"
>
ชื่อบริษัท
</label>
<input
type=
"text"
class=
"form-control w-full !rounded-md"
id=
"first-name"
[(
ngModel
)]="
companyModel
.
companyName
"
placeholder=
"ชื่อบริษัท"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"first-name"
class=
"form-label"
>
รหัสบริษัท
</label>
<input
type=
"text"
class=
"form-control w-full !rounded-md"
id=
"first-name"
placeholder=
"CODE"
[(
ngModel
)]="
companyModel
.
companyCode
"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"bio"
class=
"form-label"
>
เกี่ยวกับบริษัท :
</label>
<textarea
class=
"form-control w-full !rounded-md dark:!text-defaulttextcolor/70"
id=
"bio"
rows=
"5"
[(
ngModel
)]="
companyModel
.
companyInfo
"
></textarea>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"bio"
class=
"form-label"
>
ที่อยู่ :
</label>
<textarea
class=
"form-control w-full !rounded-md dark:!text-defaulttextcolor/70"
id=
"bio"
rows=
"5"
[(
ngModel
)]="
companyModel
.
address
"
></textarea>
</div>
</div>
<h6
class=
"font-semibold mb-4 text-[1rem]"
>
ข้อมูลเจ้าของบริษัท :
</h6>
<div
class=
"sm:grid grid-cols-12 gap-6 mb-6"
>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"email-address"
class=
"form-label"
>
ชื่อ-สกุล :
</label>
<input
type=
"text"
class=
"form-control w-full !rounded-md"
id=
"email-address"
[(
ngModel
)]="
companyModel
.
ownerName
"
placeholder=
"ชื่อ-สกุล"
>
</div>
<div
class=
"xl:col-span-6 col-span-12"
>
<label
for=
"Contact-Details"
class=
"form-label"
>
เบอร์ติดต่อ :
</label>
<input
type=
"text"
class=
"form-control w-full !rounded-md"
id=
"Contact-Details"
[(
ngModel
)]="
companyModel
.
contact
"
placeholder=
"การติดต่อ"
>
</div>
</div>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"ltr:float-right rtl:float-left"
>
<button
type=
"button"
class=
"ti-btn bg-primary text-white m-1"
(
click
)="
save
()"
>
บันทึกการเปลี่ยนแปลง
</button>
<button
type=
"button"
class=
"ti-btn ti-btn-ghost-secondary ti-btn-wave"
(
click
)="
reset
()"
>
ยกเลิก
</button>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-4 col-span-12"
>
<div
class=
"box custom-box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
แผนที่บริษัท
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"grid grid-cols-12 sm:gap-6"
>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-6 col-span-6"
>
<label
for=
"input-label"
class=
"form-label"
>
{{"ละติจูด" | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"input"
[(
ngModel
)]="
companyModel
.
latitude
"
(
ngModelChange
)="
changeMarker
()"
>
</div>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-6 col-span-6"
>
<label
for=
"input-label"
class=
"form-label"
>
{{"ลองจิจูด" | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"input"
[(
ngModel
)]="
companyModel
.
longitude
"
(
ngModelChange
)="
changeMarker
()"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<input
id=
"searchBox"
#
searchBox
type=
"text"
placeholder=
"ค้นหาสถานที่..."
class=
"form-control w-full p-2 border rounded mb-3"
>
</div>
<google-map
class=
"xl:col-span-12 col-span-12"
height=
"400px"
[
center
]="{
lat:
companyModel
.
latitude
,
lng:
companyModel
.
longitude
}"
[
zoom
]="
12
"
(
mapClick
)="
addMarker
($
event
,
mapMarker
)"
>
<map-marker
#
mapMarker=
"mapMarker"
[
position
]="{
lat:
companyModel
.
latitude
,
lng:
companyModel
.
longitude
}"
[
options
]="
markerOptions
"
/>
</google-map>
</div>
</div>
</div>
</div>
</div>
</div>
<!--End::row-1 -->
src/app/portal-manage/company-management/company-info/company-info.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
CommonModule
}
from
"@angular/common"
;
import
{
ChangeDetectionStrategy
,
Component
,
ElementRef
,
ViewChild
,
ViewEncapsulation
}
from
'@angular/core'
;
import
{
SharedModule
}
from
"../../../shared/shared.module"
;
import
{
GoogleMapsModule
,
MapInfoWindow
,
MapMarker
}
from
'@angular/google-maps'
;
import
{
NgSelectModule
}
from
"@ng-select/ng-select"
;
import
{
ActivatedRoute
,
Router
}
from
"@angular/router"
;
import
{
TokenService
}
from
"../../../shared/services/token.service"
;
import
{
CompanyService
}
from
"../../services/company.service"
;
import
{
CompanyModel
}
from
"../../models/company.model"
;
import
{
FormsModule
}
from
"@angular/forms"
;
import
{
FileUploadModule
}
from
'ng2-file-upload'
;
import
{
FileItem
,
FileUploader
,
ParsedResponseHeaders
}
from
"ng2-file-upload"
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
swal
from
'sweetalert'
;
import
{
environment
}
from
"../../../../environments/environment"
;
@
Component
({
selector
:
'app-company-info'
,
standalone
:
true
,
imports
:
[
SharedModule
,
NgSelectModule
,
CommonModule
,
FormsModule
,
FileUploadModule
,
TranslateModule
,
NgSelectModule
,
GoogleMapsModule
,
MapMarker
],
templateUrl
:
'./company-info.component.html'
,
styleUrl
:
'./company-info.component.css'
,
encapsulation
:
ViewEncapsulation
.
None
})
export
class
CompanyInfoComponent
{
@
ViewChild
(
MapInfoWindow
)
infoWindow
:
MapInfoWindow
|
undefined
;
center
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
zoom
=
4
;
markerOptions
:
google
.
maps
.
MarkerOptions
=
{
draggable
:
false
};
markerPositions
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
companyId
=
""
companyModel
:
CompanyModel
=
new
CompanyModel
()
uploaderProfile
:
FileUploader
|
undefined
;
uploadErrorMsg
:
string
=
""
;
@
ViewChild
(
'searchBox'
,
{
static
:
false
})
searchBoxElement
!
:
ElementRef
;
constructor
(
private
router
:
Router
,
private
route
:
ActivatedRoute
,
private
comService
:
CompanyService
,
private
tokenService
:
TokenService
)
{
this
.
companyId
=
this
.
tokenService
.
getSelectCompany
().
companyId
;
this
.
getCompanyInfo
()
this
.
uploadConfig
()
}
async
ngAfterViewInit
()
{
// await this.loadGoogleMapsAPI();
this
.
initAutocomplete
();
}
initAutocomplete
()
{
if
(
!
this
.
searchBoxElement
||
!
this
.
searchBoxElement
.
nativeElement
)
{
console
.
error
(
"❌ SearchBox element not found!"
);
return
;
}
const
input
=
this
.
searchBoxElement
.
nativeElement
;
const
searchBox
=
new
google
.
maps
.
places
.
SearchBox
(
input
);
searchBox
.
addListener
(
'places_changed'
,
()
=>
{
const
places
=
searchBox
.
getPlaces
();
if
(
!
places
||
places
.
length
===
0
)
return
;
const
place
=
places
[
0
];
if
(
!
place
.
geometry
||
!
place
.
geometry
.
location
)
return
;
this
.
companyModel
.
latitude
=
place
.
geometry
.
location
.
lat
()
this
.
companyModel
.
longitude
=
place
.
geometry
.
location
.
lng
()
// this.center = {
// lat: place.geometry.location.lat(),
// lng: place.geometry.location.lng(),
// };
// this.markerPositions = this.center;
// console.log(`📍 New Location: ${this.center.lat}, ${this.center.lng}`);
});
}
uploadConfig
()
{
this
.
uploaderProfile
=
new
FileUploader
({
url
:
environment
.
baseUrl
+
"/api/upload-image"
,
isHTML5
:
true
,
authToken
:
this
.
tokenService
.
getToken
()
!
,
});
this
.
uploaderProfile
.
onAfterAddingFile
=
(
fileItem
:
FileItem
)
=>
{
fileItem
.
withCredentials
=
false
;
this
.
uploadErrorMsg
=
""
;
while
(
this
.
uploaderProfile
!
.
queue
.
length
>
1
)
{
this
.
uploaderProfile
!
.
queue
[
0
].
remove
();
}
if
(
fileItem
.
file
.
size
>
5000000
)
{
this
.
uploadErrorMsg
=
"maximum file size 5mb."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
fileItem
.
isCancel
=
true
;
return
;
}
if
(
fileItem
.
file
.
type
!
.
indexOf
(
"image"
)
===
-
1
)
{
this
.
uploadErrorMsg
=
"please upload image only."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
fileItem
.
isCancel
=
true
;
return
;
}
fileItem
.
upload
();
};
this
.
uploaderProfile
.
onCompleteItem
=
(
item
:
FileItem
,
response
:
string
,
status
:
number
,
headers
:
ParsedResponseHeaders
)
=>
{
if
(
item
.
isSuccess
)
{
const
res
=
JSON
.
parse
(
response
);
console
.
log
(
"res"
,
res
);
this
.
companyModel
.
picture
=
res
.
filename
swal
(
res
.
message
,
"บันทึกสำเร็จ"
,
"success"
);
}
else
{
this
.
uploadErrorMsg
=
"cannot upload file."
;
swal
(
"Opp!!"
,
"ไม่สามารถอัพโหลดได้"
,
"info"
);
}
};
}
changeMarker
()
{
this
.
markerPositions
=
{
lat
:
this
.
companyModel
.
latitude
,
lng
:
this
.
companyModel
.
longitude
}
}
addMarker
(
event
:
google
.
maps
.
MapMouseEvent
,
marker
:
MapMarker
)
{
console
.
log
(
event
)
console
.
log
(
marker
)
this
.
companyModel
.
latitude
=
event
.
latLng
!
.
toJSON
().
lat
this
.
companyModel
.
longitude
=
event
.
latLng
!
.
toJSON
().
lng
this
.
markerPositions
=
{
lat
:
event
.
latLng
!
.
toJSON
().
lat
,
lng
:
event
.
latLng
!
.
toJSON
().
lng
}
if
(
this
.
infoWindow
&&
marker
.
title
)
{
this
.
infoWindow
.
open
(
marker
);
}
}
getCompanyInfo
()
{
this
.
comService
.
getById
(
this
.
companyId
).
subscribe
(
result
=>
{
;
this
.
companyModel
=
result
this
.
tokenService
.
saveSelectCompany
(
result
);
console
.
log
(
"companyModel"
,
this
.
companyModel
)
})
}
reset
()
{
this
.
getCompanyInfo
()
}
save
()
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
this
.
comService
.
update
(
this
.
companyModel
).
subscribe
(
result
=>
{
swal
(
"Update Success!!"
,
"บันทึกข้อมูลสมาชิก"
,
"success"
);
this
.
getCompanyInfo
()
})
});
}
}
src/app/portal-manage/company-management/company-location/company-location.component.css
deleted
100644 → 0
View file @
8b2e4a55
:host
{
display
:
block
;
}
.map-container
{
width
:
100%
!important
}
src/app/portal-manage/company-management/company-location/company-location.component.html
deleted
100644 → 0
View file @
8b2e4a55
<app-page-header
[
title
]="'สถานที่การลงเวลา'"
[
activeTitle
]="'จัดการการลงเวลา'"
[
title1
]="'สถานที่การลงเวลา'"
></app-page-header>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
{{ 'All List' | translate}}
<span
class=
"badge bg-light text-default rounded-full ms-1 text-[0.75rem] align-middle"
>
{{itemsList.length}}
</span>
</div>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(
click
)="
new
()"
data-hs-overlay=
"#modal-detail"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'Create' |
translate}}
</a>
<!-- <a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-success-full me-2" *ngIf="someSelected"
(click)="adjustSelect('A')"><i class="ri-user-follow-line font-semibold align-middle"></i>{{ 'Active' |
translate}}
</a>
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-secondary-full me-2"
*ngIf="someSelected" (click)="adjustSelect('U')"><i
class="ri-user-unfollow-line font-semibold align-middle"></i>{{ 'Unactive' |
translate}}
</a> -->
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-danger-full me-2"
*
ngIf=
"someSelected"
(
click
)="
deleteSelect
()"
><i
class=
"ri-delete-bin-line font-semibold align-middle"
></i>
{{ 'Delete' |
translate}}
</a>
<div>
<input
class=
"form-control form-control"
type=
"text"
placeholder=
"ค้นหาสถานที่"
aria-label=
".form-control-sm example"
[(
ngModel
)]='
searchTerm
'
>
</div>
<!-- <div>
<input class="form-control form-control" type="text" placeholder="กรองตามบริษัท"
aria-label=".form-control-sm example" [(ngModel)]='searchTerm'>
</div> -->
<!-- <a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul> -->
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"table-responsive"
>
<table
class=
"table whitespace-nowrap min-w-full ti-custom-table-hover"
>
<thead>
<tr
class=
"border-b border-defaultborder"
>
<th
scope=
"col"
class=
"!text-start"
>
<input
class=
"form-check-input check-all"
type=
"checkbox"
id=
"all-products"
(
change
)="
toggleAll
($
event
)"
[
checked
]="
allSelected
"
aria-label=
"..."
>
</th>
<th
scope=
"col"
class=
"text-start"
>
ชื่อสถานที่
</th>
<th
scope=
"col"
class=
"text-start"
>
ละติจูด
</th>
<th
scope=
"col"
class=
"text-start"
>
ลองจิจูด
</th>
<th
scope=
"col"
class=
"text-start"
>
{{"ประเภท" | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
>
วันที่เริ่มต้น
</th>
<th
scope=
"col"
class=
"text-start"
>
วันที่สิ้นสุด
</th>
<th
scope=
"col"
class=
"text-start"
>
{{"Update Date" | translate}}
</th>
<th
scope=
"col"
class=
"text-start"
></th>
</tr>
</thead>
<tbody>
@for(item of filterList;track filterList){
<tr
class=
"border border-defaultborder dark:border-defaultborder/10"
>
<td
class=
"product-checkbox"
><input
class=
"form-check-input"
type=
"checkbox"
[
checked
]="
selectedItems
.
get
(
item
.
locationId
)"
(
change
)="
onCheckboxChange
(
item
.
locationId
)"
aria-label=
"..."
value=
""
>
</td>
<td>
<div
class=
"flex"
>
<div
class=
"ms-2"
>
<p
class=
"font-semibold mb-0 flex items-center text-primary"
><a
(
click
)="
view
(
item
)"
routerLinkActive=
"active"
>
{{item.locationName}}
</a></p>
<p
class=
"text-[0.75rem] text-muted mb-0"
>
{{item.locationId}}
</p>
</div>
</div>
</td>
<td>
{{item.latitude}}
</td>
<td>
{{item.longitude}}
</td>
<td>
<span
class=
"badge bg-{{ item.locationType == 0 ? 'primary' : 'warning'}} {{ item.locationType == 0 ? 'text-white' : ''}}"
>
{{item.getStatus()}}
</span>
</td>
<td><span
class=
"badge bg-info/10 text-primary"
><i
class=
"bi bi-clock me-1"
></i>
{{item.startDate ?
(item.startDate | date
: 'medium') : '-'}}
</span></td>
<td><span
class=
"badge bg-info/10 text-primary"
><i
class=
"bi bi-clock me-1"
></i>
{{item.endDate ?
(item.endDate | date
: 'medium') : '-'}}
</span></td>
<td><span
class=
"badge bg-info/10 text-primary"
><i
class=
"bi bi-clock me-1"
></i>
{{item.updatedAt ?
(item.updatedAt | date
: 'medium') : '-'}}
</span>
<td>
<td>
<div
class=
"flex flex-row items-center !gap-2 "
>
<a
aria-label=
"anchor"
(
click
)="
view
(
item
)"
data-hs-overlay=
"#modal-detail"
class=
"ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info"
><i
class=
"ri-pencil-line"
></i></a>
<a
aria-label=
"anchor"
href=
"javascript:void(0);"
(
click
)="
delete
(
item
)"
class=
"ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger"
><i
class=
"ri-delete-bin-line"
></i></a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div
class=
"box-footer"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterList.length > 0"
>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageIndex>0"
class=
"page-item {{pageIndex==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem]"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{'Previous' | translate}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex-1>0"
(
click
)="
pageIndex =
pageIndex-2;updatePagedItems()"
>
{{pageIndex-1}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{pageIndex}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageIndex +1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{pageIndex +2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+2;updatePagedItems()"
>
{{pageIndex +3}}
</a></li>
<li
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"box custom-box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
แผนที่บริษัท
</div>
</div>
<div
class=
"box-body"
>
<div
class=
"grid grid-cols-12 sm:gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<google-map
class=
"xl:col-span-12 col-span-12"
height=
"400px"
[
center
]="
center
"
[
zoom
]="
zoom
"
>
<map-circle
*
ngFor=
"let item of itemsList"
[
center
]="{
lat:
item
.
latitude
,
lng:
item
.
longitude
}"
[
radius
]="
item
.
radius
*
1000
"
/>
<map-marker
*
ngFor=
"let item of itemsList"
#
mapMarker=
"mapMarker"
[
position
]="{
lat:
item
.
latitude
,
lng:
item
.
longitude
}"
[
options
]="
markerOptions
"
/>
</google-map>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Start:: Create Contact -->
<div
id=
"modal-detail"
class=
"hs-overlay hidden ti-modal [--overlay-backdrop:static]"
>
<div
class=
"hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out"
>
<div
class=
"ti-modal-content"
>
<div
class=
"ti-modal-header"
>
<h6
class=
"modal-title text-[1rem] font-semibold text-defaulttextcolor"
id=
"mail-ComposeLabel"
>
{{ 'Create' |
translate }} {{ 'Location' | translate }}
</h6>
<button
type=
"button"
class=
"hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
data-hs-overlay=
"#modal-detail"
#
closeModal
>
<span
class=
"sr-only"
>
{{'Close' | translate}}
</span>
<i
class=
"ri-close-line"
></i>
</button>
</div>
<div
class=
"ti-modal-body px-4"
>
<div
class=
"grid grid-cols-12 gap-4"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'ชื่อสถานที่' | translate}}
</label>
<!-- <input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.locationName"> -->
<input
[(
ngModel
)]="
selectModel
.
locationName
"
id=
"searchBox"
#
searchBox
type=
"text"
placeholder=
"ค้นหาสถานที่..."
class=
"form-control w-full p-2 border rounded mb-3"
>
<div
class=
"text-danger"
*
ngIf=
"!selectModel.locationName"
>
{{'Please fill in information' | translate}}
</div>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
class=
"form-label"
>
{{'ประเภท' | translate}}
</label>
<ng-select
name=
"choices-multiple-remove-button2"
id=
"choices-multiple-remove-button2"
placeholder=
""
[(
ngModel
)]="
selectModel
.
locationType
"
>
<ng-option
[
value
]="
0
"
>
{{'PERMANENT' | translate}}
</ng-option>
<ng-option
[
value
]="
1
"
selected
>
{{'TEMPORARY' | translate}}
</ng-option>
</ng-select>
</div>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-12 col-span-12"
>
<label
for=
"input-date"
class=
"form-label"
>
{{ "Plan Start" | translate}}
</label>
<input
type=
"date"
class=
"form-control"
id=
"input-date"
[(
ngModel
)]="
selectModel
.
startDate
"
>
</div>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-12 col-span-12"
>
<label
for=
"input-date"
class=
"form-label"
>
{{ "Plan Start" | translate}}
</label>
<input
type=
"date"
class=
"form-control"
id=
"input-date"
[(
ngModel
)]="
selectModel
.
endDate
"
>
</div>
</div>
<div
class=
"grid grid-cols-12 sm:gap-6"
>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-6 col-span-6"
>
<label
for=
"input-label"
class=
"form-label"
>
{{"ละติจูด" | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"input"
[(
ngModel
)]="
selectModel
.
latitude
"
(
ngModelChange
)="
changeMarker
()"
>
</div>
<div
class=
"xl:col-span-6 lg:col-span-6 md:col-span-6 sm:col-span-6 col-span-6"
>
<label
for=
"input-label"
class=
"form-label"
>
{{"ลองจิจูด" | translate}}
</label>
<input
type=
"text"
class=
"form-control"
id=
"input"
[(
ngModel
)]="
selectModel
.
longitude
"
(
ngModelChange
)="
changeMarker
()"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<label
for=
"deal-title"
class=
"form-label"
>
{{'รัศมี (KM)' | translate}}
</label>
<!-- <input type="text" class="form-control" id="deal-title" placeholder=""
[(ngModel)]="selectModel.locationName"> -->
<input
[(
ngModel
)]="
selectModel
.
radius
"
type=
"number"
placeholder=
"รัศมี"
class=
"form-control w-full p-2 border rounded mb-3"
>
</div>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"mb-4"
>
</div>
<google-map
class=
"xl:col-span-12 col-span-12"
height=
"400px"
[
center
]="{
lat:
selectModel
.
latitude
,
lng:
selectModel
.
longitude
}"
[
zoom
]="
12
"
(
mapClick
)="
addMarker
($
event
,
mapMarker
)"
>
<map-circle
[
center
]="{
lat:
selectModel
.
latitude
,
lng:
selectModel
.
longitude
}"
[
radius
]="
selectModel
.
radius
*
1000
"
/>
<map-marker
#
mapMarker=
"mapMarker"
[
position
]="{
lat:
selectModel
.
latitude
,
lng:
selectModel
.
longitude
}"
[
options
]="
markerOptions
"
/>
</google-map>
</div>
</div>
</div>
<div
class=
"ti-modal-footer"
>
<button
type=
"button"
class=
"hs-dropdown-toggle ti-btn ti-btn-light align-middle"
data-hs-overlay=
"#modal-detail"
>
{{'Cancel' | translate}}
</button>
<button
type=
"button"
(
click
)="
save
()"
class=
"ti-btn bg-primary text-white !font-medium"
>
{{'Save' |
translate}}
</button>
</div>
</div>
</div>
</div>
<!-- End:: Create Contact -->
src/app/portal-manage/company-management/company-location/company-location.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
CommonModule
}
from
"@angular/common"
;
import
{
ChangeDetectionStrategy
,
Component
,
ElementRef
,
ViewChild
,
ViewEncapsulation
}
from
'@angular/core'
;
import
{
SharedModule
}
from
"../../../shared/shared.module"
;
import
{
NgSelectModule
}
from
"@ng-select/ng-select"
;
import
{
CompanyLocationModel
}
from
"../../models/company-location.model"
;
import
{
CompanyLocationService
}
from
"../../services/company-location.service"
;
import
{
TokenService
}
from
"../../../shared/services/token.service"
;
import
swal
from
'sweetalert'
;
import
{
TranslateModule
,
TranslateService
}
from
"@ngx-translate/core"
;
import
{
FormsModule
}
from
"@angular/forms"
;
import
{
RouterModule
}
from
"@angular/router"
;
import
{
GoogleMap
,
GoogleMapsModule
,
MapInfoWindow
,
MapMarker
}
from
"@angular/google-maps"
;
@
Component
({
selector
:
'app-company-location'
,
standalone
:
true
,
imports
:
[
CommonModule
,
SharedModule
,
TranslateModule
,
NgSelectModule
,
FormsModule
,
GoogleMapsModule
,
MapMarker
],
templateUrl
:
'./company-location.component.html'
,
styleUrl
:
'./company-location.component.css'
,
encapsulation
:
ViewEncapsulation
.
None
})
export
class
CompanyLocationComponent
{
@
ViewChild
(
'searchBox'
,
{
static
:
false
})
searchBoxElement
!
:
ElementRef
;
@
ViewChild
(
GoogleMap
)
map
!
:
GoogleMap
;
@
ViewChild
(
MapInfoWindow
)
infoWindow
:
MapInfoWindow
|
undefined
;
@
ViewChild
(
'closeModal'
)
public
childModal
?:
ElementRef
;
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
action
=
"new"
;
allSelected
=
false
;
someSelected
=
false
;
itemsList
:
CompanyLocationModel
[]
=
[]
filterList
:
CompanyLocationModel
[]
=
[]
selectModel
:
CompanyLocationModel
=
new
CompanyLocationModel
()
empList
:
CompanyLocationModel
[]
=
[]
selectedItems
=
new
Map
<
string
,
boolean
>
();
descName
=
'engName'
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
()
}
}
center
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
zoom
=
5
;
radius
=
50
;
markerOptions
:
google
.
maps
.
MarkerOptions
=
{
draggable
:
false
};
markerPositions
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
autocompleteInput
:
string
=
''
;
_searchTerm
=
""
;
companyId
=
""
adressType
:
string
=
'geocode'
;
@
ViewChild
(
'addresstext'
)
addresstext
:
any
;
constructor
(
private
comLocationService
:
CompanyLocationService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
)
{
this
.
companyId
=
this
.
tokenService
.
getSelectCompany
().
companyId
;;
this
.
getLocation
()
}
ngOnInit
():
void
{}
async
ngAfterViewInit
()
{
// await this.loadGoogleMapsAPI();
this
.
initAutocomplete
();
}
initAutocomplete
()
{
if
(
!
this
.
searchBoxElement
||
!
this
.
searchBoxElement
.
nativeElement
)
{
console
.
error
(
"❌ SearchBox element not found!"
);
return
;
}
const
input
=
this
.
searchBoxElement
.
nativeElement
;
const
searchBox
=
new
google
.
maps
.
places
.
SearchBox
(
input
);
searchBox
.
addListener
(
'places_changed'
,
()
=>
{
const
places
=
searchBox
.
getPlaces
();
if
(
!
places
||
places
.
length
===
0
)
return
;
const
place
=
places
[
0
];
if
(
!
place
.
geometry
||
!
place
.
geometry
.
location
)
return
;
this
.
selectModel
.
latitude
=
place
.
geometry
.
location
.
lat
()
this
.
selectModel
.
longitude
=
place
.
geometry
.
location
.
lng
()
this
.
selectModel
.
locationName
=
place
.
name
!
// this.center = {
// lat: place.geometry.location.lat(),
// lng: place.geometry.location.lng(),
// };
// this.markerPositions = this.center;
// console.log(`📍 New Location: ${this.center.lat}, ${this.center.lng}`);
});
}
getLocation
()
{
this
.
comLocationService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
itemsList
=
result
this
.
updatePagedItems
()
})
}
filter
(
v
:
string
)
{
return
this
.
itemsList
?.
filter
(
(
x
)
=>
x
.
locationId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
locationName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getStatus
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
delete
(
item
:
CompanyLocationModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"You won't be able to revert this!"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"Cancel"
,
"Yes,Delete it!"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
comLocationService
.
delete
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getLocation
()
})
}
});
}
new
()
{
this
.
action
=
'add'
this
.
selectModel
=
new
CompanyLocationModel
()
this
.
selectModel
.
latitude
=
0.00
this
.
selectModel
.
longitude
=
0.00
}
view
(
item
:
CompanyLocationModel
)
{
this
.
action
=
'edit'
this
.
selectModel
=
new
CompanyLocationModel
(
item
)
this
.
markerPositions
=
{
lat
:
this
.
selectModel
.
latitude
,
lng
:
this
.
selectModel
.
longitude
}
console
.
log
(
this
.
selectModel
)
}
save
()
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
if
(
this
.
action
==
'add'
)
{
this
.
comLocationService
.
save
(
this
.
companyId
,
this
.
selectModel
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getLocation
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
else
if
(
this
.
action
==
'edit'
)
{
this
.
comLocationService
.
update
(
this
.
companyId
,
this
.
selectModel
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getLocation
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
}
});
}
updatePagedItems
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
this
.
filterList
=
this
.
itemsList
.
slice
(
startIndex
,
endIndex
);
}
toggleAll
(
event
:
any
)
{
this
.
allSelected
=
event
.
target
.
checked
;
this
.
selectedItems
.
clear
();
this
.
itemsList
.
forEach
(
item
=>
{
this
.
selectedItems
.
set
(
item
.
locationId
,
this
.
allSelected
);
});
this
.
someSelected
=
this
.
itemsList
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
locationId
));
}
onCheckboxChange
(
locationId
:
string
)
{
const
isSelected
=
this
.
selectedItems
.
get
(
locationId
)
||
false
;
this
.
selectedItems
.
set
(
locationId
,
!
isSelected
);
this
.
allSelected
=
this
.
itemsList
.
every
(
item
=>
this
.
selectedItems
.
get
(
item
.
locationId
));
this
.
someSelected
=
this
.
itemsList
.
some
(
item
=>
this
.
selectedItems
.
get
(
item
.
locationId
));
}
deleteSelect
()
{
let
employeeInfo
=
''
;
this
.
selectedItems
.
forEach
((
isSelected
,
locationId
)
=>
{
if
(
isSelected
)
{
const
item
=
this
.
itemsList
.
find
(
item
=>
item
.
locationId
===
locationId
);
if
(
item
)
{
employeeInfo
+=
`
${
this
.
translate
.
instant
(
'ชื่อตำแหน่ง'
)}
:
${
item
.
locationName
}
\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
,
locationId
)
=>
{
if
(
isSelected
)
{
const
item
=
this
.
itemsList
.
find
(
item
=>
item
.
locationId
===
locationId
);
if
(
item
)
{
this
.
comLocationService
.
delete
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getLocation
();
});
}
}
});
}
});
}
changeMarker
()
{
this
.
markerPositions
=
{
lat
:
this
.
selectModel
.
latitude
,
lng
:
this
.
selectModel
.
longitude
}
}
addMarker
(
event
:
google
.
maps
.
MapMouseEvent
,
marker
:
MapMarker
)
{
console
.
log
(
event
)
console
.
log
(
marker
)
this
.
selectModel
.
latitude
=
event
.
latLng
!
.
toJSON
().
lat
this
.
selectModel
.
longitude
=
event
.
latLng
!
.
toJSON
().
lng
this
.
markerPositions
=
{
lat
:
event
.
latLng
!
.
toJSON
().
lat
,
lng
:
event
.
latLng
!
.
toJSON
().
lng
}
if
(
this
.
infoWindow
&&
marker
.
title
)
{
this
.
infoWindow
.
open
(
marker
);
}
}
}
src/app/portal-manage/company-management/company-management.component.css
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/company-management/company-management.component.html
deleted
100644 → 0
View file @
8b2e4a55
<p>
company-management works!
</p>
src/app/portal-manage/company-management/company-management.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
Component
}
from
'@angular/core'
;
@
Component
({
selector
:
'app-company-management'
,
template
:
`
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Company Management</h4>
</div>
<div class="card-body">
<p>ยินดีต้อนรับสู่ระบบจัดการบริษัท</p>
<p>ระบบจัดการข้อมูลบริษัทและพนักงาน</p>
</div>
</div>
</div>
</div>
</div>
`
,
styles
:
[
`
.card {
margin: 20px 0;
}
.card-header {
background-color: #f8f9fa;
border-bottom: 1px solid #dee2e6;
}
`
]
})
export
class
CompanyManagementComponent
{
constructor
()
{
}
}
src/app/portal-manage/company-management/company-management.module.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
NgModule
}
from
'@angular/core'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
RouterModule
,
Routes
}
from
'@angular/router'
;
import
{
CompanyManagementComponent
}
from
'./company-management.component'
;
export
const
routes
:
Routes
=
[
{
path
:
''
,
component
:
CompanyManagementComponent
}
];
@
NgModule
({
declarations
:
[
CompanyManagementComponent
],
imports
:
[
CommonModule
,
RouterModule
.
forChild
(
routes
)
],
exports
:
[
CompanyManagementComponent
]
})
export
class
CompanyManagementModule
{
static
routes
=
routes
;
}
src/app/portal-manage/company-management/enroll-face/enroll-face.component.html
deleted
100644 → 0
View file @
8b2e4a55
<video
#
video
width=
"640"
height=
"480"
style=
"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;"
autoplay
(
loadedmetadata
)="
detectFace
()"
>
</video>
<!-- Canvas element -->
<canvas
#
canvas
width=
"640"
height=
"480"
style=
"position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;"
>
</canvas>
<button
*
ngIf=
"checkMatch"
style=
"position: absolute; left: 0;bottom: 0;margin-bottom: 3rem;width: 100%;"
type=
"button"
class=
"ti-btn bg-primary text-white !font-medium"
(
click
)="
captureImage
()"
>
ตรวจสอบใบหน้า
</button>
src/app/portal-manage/company-management/enroll-face/enroll-face.component.scss
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/company-management/enroll-face/enroll-face.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
HttpClient
}
from
'@angular/common/http'
;
import
{
Component
,
ElementRef
,
ViewChild
}
from
'@angular/core'
;
import
{
ActivatedRoute
}
from
'@angular/router'
;
import
*
as
faceapi
from
'face-api.js'
;
import
swal
from
'sweetalert'
;
import
{
environment
}
from
'../../../../environments/environment'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
TokenService
}
from
'../../../shared/services/token.service'
;
import
{
SharedModule
}
from
'../../../shared/shared.module'
;
import
{
TimestampModel
}
from
'../../models/timestamp.model'
;
import
{
EmployeeModel
}
from
'../../models/employee.model'
;
import
{
TimestampService
}
from
'../../services/timestamp.service'
;
import
{
EmployeeService
}
from
'../../services/employee.service'
;
import
{
CompanyLocationModel
}
from
'../../models/company-location.model'
;
import
{
CompanyLocationService
}
from
'../../services/company-location.service'
;
@
Component
({
selector
:
'app-enroll-face'
,
standalone
:
true
,
imports
:
[
CommonModule
,
SharedModule
],
templateUrl
:
'./enroll-face.component.html'
,
styleUrl
:
'./enroll-face.component.scss'
})
export
class
EnrollFaceComponent
{
@
ViewChild
(
'video'
)
video
:
ElementRef
;
@
ViewChild
(
'canvas'
)
canvas
:
ElementRef
;
locationList
:
CompanyLocationModel
[]
=
[]
locationArea
:
CompanyLocationModel
[]
=
[]
capturedImage
:
string
|
null
=
null
;
uploadStatus
:
string
=
''
;
checkMatch
=
false
;
companyId
=
""
memberId
=
""
timestampModel
:
TimestampModel
=
new
TimestampModel
()
employeeModel
:
EmployeeModel
=
new
EmployeeModel
()
location
:
{
latitude
:
number
;
longitude
:
number
}
=
{
latitude
:
0
,
longitude
:
0
};
errorMessage
:
string
|
null
=
null
;
constructor
(
private
http
:
HttpClient
,
private
timestampService
:
TimestampService
,
private
tokenService
:
TokenService
,
private
employeeService
:
EmployeeService
,
private
comLocationService
:
CompanyLocationService
)
{
this
.
companyId
=
this
.
tokenService
.
getSelectCompany
().
companyId
;
// this.employeeService.getMemberById(this.tokenService.getSelectCompany().companyId, this.memberId).subscribe(result => {
// this.employeeModel = result
// })
}
ngOnInit
()
{
this
.
getCurrentLocation
()
// โหลดโมเดล Face Detection ของ face-api.js
faceapi
.
nets
.
tinyFaceDetector
.
loadFromUri
(
'/assets/models/tiny_face_detector'
);
faceapi
.
nets
.
faceLandmark68Net
.
loadFromUri
(
'/assets/models/face_landmark_68'
);
faceapi
.
nets
.
faceRecognitionNet
.
loadFromUri
(
'/assets/models/face_recognition'
);
faceapi
.
nets
.
faceExpressionNet
.
loadFromUri
(
'/assets/models/face_expression'
);
// เปิดกล้อง
this
.
startVideo
();
this
.
getCompanyLocation
()
}
getCompanyLocation
()
{
this
.
comLocationService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
locationList
=
result
this
.
getCurrentLocation
()
})
}
startVideo
():
void
{
navigator
.
mediaDevices
.
getUserMedia
({
video
:
true
})
.
then
(
stream
=>
{
this
.
video
.
nativeElement
.
srcObject
=
stream
;
})
.
catch
(
err
=>
{
console
.
error
(
'Error accessing camera: '
,
err
);
});
}
// ตรวจจับใบหน้าและวาดกรอบครอบใบหน้า
async
detectFace
()
{
const
videoEl
=
this
.
video
.
nativeElement
;
const
displaySize
=
{
width
:
videoEl
.
width
,
height
:
videoEl
.
height
};
faceapi
.
matchDimensions
(
this
.
canvas
.
nativeElement
,
displaySize
);
setInterval
(
async
()
=>
{
const
detections
=
await
faceapi
.
detectAllFaces
(
videoEl
,
new
faceapi
.
TinyFaceDetectorOptions
()).
withFaceLandmarks
().
withFaceExpressions
()
const
resizedDetections
=
faceapi
.
resizeResults
(
detections
,
displaySize
);
// ล้าง canvas ก่อนวาดใหม่
this
.
canvas
.
nativeElement
.
getContext
(
'2d'
).
clearRect
(
0
,
0
,
displaySize
.
width
,
displaySize
.
height
);
// วาดกรอบครอบใบหน้าลงบน canvas
faceapi
.
draw
.
drawDetections
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
faceapi
.
draw
.
drawFaceExpressions
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
faceapi
.
draw
.
drawFaceLandmarks
(
this
.
canvas
.
nativeElement
,
resizedDetections
);
if
(
detections
.
length
>
0
)
{
this
.
checkMatch
=
true
}
else
{
this
.
checkMatch
=
false
}
},
100
);
// ตรวจจับทุกๆ 100ms
}
// // แคปเจอร์ภาพจากกล้อง
captureImage
():
void
{
const
video
=
this
.
video
.
nativeElement
;
const
canvas
=
this
.
canvas
.
nativeElement
;
const
context
=
canvas
.
getContext
(
'2d'
);
// วาดภาพจาก video ลงใน canvas
context
.
drawImage
(
video
,
0
,
0
,
canvas
.
width
,
canvas
.
height
);
// แปลงภาพใน canvas เป็น base64
this
.
capturedImage
=
canvas
.
toDataURL
(
'image/jpeg'
);
// console.log(this.capturedImage)
// this.uploadImage() checkface
this
.
uploadImage
()
}
// // อัปโหลดภาพที่แคปเจอร์แล้ว
uploadImage
():
void
{
if
(
this
.
capturedImage
)
{
const
file
=
this
.
dataURLtoFile
(
this
.
capturedImage
,
'face.jpg'
);
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
this
.
http
.
post
(
environment
.
baseUrl
+
`/face/members/check-face-emp`
,
formData
).
subscribe
({
next
:
(
response
:
any
)
=>
{
this
.
employeeService
.
getMemberById
(
this
.
tokenService
.
getSelectCompany
().
companyId
,
response
.
message
).
subscribe
(
result
=>
{
this
.
employeeModel
=
result
this
.
timestampModel
=
new
TimestampModel
({
"company_employeeId"
:
this
.
employeeModel
.
company_employeeId
,
"timestampType"
:
1
,
"latitude"
:
this
.
location
?.
latitude
,
"longitude"
:
this
.
location
?.
longitude
})
this
.
uploadPhototimestamp
();
})
},
error
:
(
error
)
=>
{
swal
(
"Face Check Failed"
,
this
.
uploadStatus
,
"error"
);
}
});
}
}
uploadPhototimestamp
()
{
const
base64ImagePayload
=
{
base64_image
:
this
.
capturedImage
// Ensure `capturedImage` includes the full base64 string (e.g., "data:image/png;base64,...")
};
const
file
=
this
.
dataURLtoFile
(
this
.
capturedImage
!
,
'face.jpg'
);
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
this
.
http
.
post
(
environment
.
baseUrl
+
`/api/upload-image/`
,
formData
).
subscribe
({
next
:
(
response
:
any
)
=>
{
console
.
log
(
'Upload successful:'
,
response
);
this
.
timestampModel
.
photoTimestamp
=
response
.
filename
this
.
saveTimestamp
()
},
error
:
(
error
)
=>
{
console
.
error
(
'Error uploading image:'
,
error
);
alert
(
'Error: '
+
error
.
error
.
detail
||
'Upload failed.'
);
}
});
}
saveTimestamp
()
{
if
(
this
.
locationArea
.
length
>
0
)
{
this
.
timestampModel
.
timestampType
=
1
this
.
timestampModel
.
locationName
=
this
.
locationArea
[
0
].
locationName
}
else
{
this
.
timestampModel
.
timestampType
=
0
}
this
.
timestampService
.
save
(
this
.
companyId
,
this
.
timestampModel
).
subscribe
(
result
=>
{
swal
(
result
.
timestampType
==
0
?
"Warning Location !!"
:
"Complete !!"
,
"ลงเวลาการทำงาน "
+
this
.
employeeModel
.
getFullname
()
+
" เวลา "
+
new
Date
(
result
.
timestamp
).
toLocaleTimeString
(
"th"
,
{
hour
:
'2-digit'
,
minute
:
'2-digit'
}),
result
.
timestampType
==
0
?
"info"
:
"success"
);
})
}
// // แปลง Base64 เป็นไฟล์ (Blob)
dataURLtoFile
(
dataurl
:
string
,
filename
:
string
):
File
{
const
arr
:
any
=
dataurl
.
split
(
','
);
const
mime
=
arr
[
0
].
match
(
/:
(
.*
?)
;/
)[
1
];
const
bstr
=
atob
(
arr
[
1
]);
let
n
=
bstr
.
length
;
const
u8arr
=
new
Uint8Array
(
n
);
while
(
n
--
)
{
u8arr
[
n
]
=
bstr
.
charCodeAt
(
n
);
}
return
new
File
([
u8arr
],
filename
,
{
type
:
mime
});
}
getCurrentLocation
()
{
if
(
navigator
.
geolocation
)
{
navigator
.
geolocation
.
getCurrentPosition
(
(
position
)
=>
{
this
.
location
=
{
latitude
:
position
.
coords
.
latitude
,
longitude
:
position
.
coords
.
longitude
,
};
this
.
searchCompanyLocation
()
this
.
errorMessage
=
null
;
// Clear any previous errors
console
.
log
(
'Location fetched successfully:'
,
this
.
location
);
},
(
error
)
=>
{
switch
(
error
.
code
)
{
case
error
.
PERMISSION_DENIED
:
this
.
errorMessage
=
'Permission denied by the user.'
;
break
;
case
error
.
POSITION_UNAVAILABLE
:
this
.
errorMessage
=
'Location information is unavailable.'
;
break
;
case
error
.
TIMEOUT
:
this
.
errorMessage
=
'The request to get user location timed out.'
;
break
;
default
:
this
.
errorMessage
=
'An unknown error occurred.'
;
}
console
.
error
(
'Error fetching location:'
,
this
.
errorMessage
);
}
);
}
else
{
this
.
errorMessage
=
'Geolocation is not supported by this browser.'
;
}
}
private
toRad
(
value
:
number
):
number
{
return
(
value
*
Math
.
PI
)
/
180
;
}
getDistance
(
lat1
:
string
,
lon1
:
string
,
lat2
:
string
,
lon2
:
string
):
number
{
const
R
=
6371
;
// รัศมีของโลกในหน่วยกิโลเมตร
const
dLat
=
this
.
toRad
(
parseFloat
(
lat2
)
-
parseFloat
(
lat1
));
const
dLon
=
this
.
toRad
(
parseFloat
(
lon2
)
-
parseFloat
(
lon1
));
const
a
=
Math
.
sin
(
dLat
/
2
)
*
Math
.
sin
(
dLat
/
2
)
+
Math
.
cos
(
this
.
toRad
(
parseFloat
(
lat1
)))
*
Math
.
cos
(
this
.
toRad
(
parseFloat
(
lat2
)))
*
Math
.
sin
(
dLon
/
2
)
*
Math
.
sin
(
dLon
/
2
);
const
c
=
2
*
Math
.
atan2
(
Math
.
sqrt
(
a
),
Math
.
sqrt
(
1
-
a
));
const
distance
=
R
*
c
;
return
distance
;
}
searchCompanyLocation
()
{
this
.
locationArea
=
this
.
getFilteredLocations
();
console
.
log
(
"locationArea"
,
this
.
locationArea
)
}
getFilteredLocations
():
CompanyLocationModel
[]
{
return
this
.
locationList
.
filter
(
location
=>
{
const
distance
=
this
.
getDistance
(
this
.
location
.
latitude
.
toString
(),
this
.
location
.
longitude
.
toString
(),
location
.
latitude
.
toString
(),
location
.
longitude
.
toString
()
);
return
distance
<=
location
.
radius
;
});
}
}
src/app/portal-manage/company-management/home-installer/home-installer.component.css
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/company-management/home-installer/home-installer.component.html
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/company-management/home-installer/home-installer.component.spec.ts
deleted
100644 → 0
View file @
8b2e4a55
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
HomeInstallerComponent
}
from
'./home-installer.component'
;
describe
(
'HomeInstallerComponent'
,
()
=>
{
let
component
:
HomeInstallerComponent
;
let
fixture
:
ComponentFixture
<
HomeInstallerComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
HomeInstallerComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
HomeInstallerComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/portal-manage/company-management/home-installer/home-installer.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
CommonModule
}
from
'@angular/common'
;
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
SharedModule
}
from
'../../../shared/shared.module'
;
import
{
TranslateModule
}
from
'@ngx-translate/core'
;
import
{
ActivatedRoute
,
Router
}
from
'@angular/router'
;
import
{
CompanyService
}
from
'../../services/company.service'
;
import
{
TokenService
}
from
'../../../shared/services/token.service'
;
@
Component
({
selector
:
'app-home-installer'
,
templateUrl
:
'./home-installer.component.html'
,
standalone
:
true
,
imports
:
[
CommonModule
,
SharedModule
,
TranslateModule
],
styleUrls
:
[
'./home-installer.component.css'
]
})
export
class
HomeInstallerComponent
implements
OnInit
{
companyId
=
""
constructor
(
private
router
:
Router
,
private
route
:
ActivatedRoute
,
private
comService
:
CompanyService
,
private
tokenService
:
TokenService
)
{
this
.
companyId
=
this
.
route
.
snapshot
.
paramMap
.
get
(
'companyId'
)
!
;
this
.
comService
.
getById
(
this
.
companyId
).
subscribe
(
result
=>
{
console
.
log
(
"SAVEEE"
)
this
.
tokenService
.
saveSelectCompany
(
result
);
// this.router.navigate(["/company"]);
})
}
ngOnInit
()
{
}
}
src/app/portal-manage/company-management/timestamp-log/timestamp-log.component.css
deleted
100644 → 0
View file @
8b2e4a55
:host
{
display
:
block
;
}
.map-container
{
width
:
100%
!important
}
src/app/portal-manage/company-management/timestamp-log/timestamp-log.component.html
deleted
100644 → 0
View file @
8b2e4a55
<app-page-header
[
title
]="'ข้อมูลการลงเวลา'"
[
activeTitle
]="'จัดการข้อมูลการลงเวลา'"
[
title1
]="'ข้อมูลการลงเวลา'"
></app-page-header>
<!-- Start::row-1 -->
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xl:col-span-12 col-span-12"
>
<div
class=
"flex flex-wrap gap-2"
>
<a
href=
"javascript:void(0);"
class=
"hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
routerLink=
"/company/timestamp-face"
><i
class=
"ri-add-line font-semibold align-middle"
></i>
{{ 'ลงเวลาพนักงาน' |
translate}}
</a>
<!-- <a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !py-1 !px-2" aria-expanded="false">
เรียงตาม<i class="ri-arrow-down-s-line align-middle ms-1 inline-block"></i>
</a>
<ul class="hs-dropdown-menu ti-dropdown-menu hidden" role="menu">
<li><a class="ti-dropdown-item" href="javascript:void(0);">Posted Date</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Status</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Department</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Job Type</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Newest</a></li>
<li><a class="ti-dropdown-item" href="javascript:void(0);">Oldest</a></li>
</ul> -->
</div>
</div>
<div
class=
"xxl:col-span-12 xl:col-span-8 col-span-12"
>
<div
class=
"grid grid-cols-12 gap-6 items-center mb-6"
>
<div
class=
"lg:col-span-12 col-span-12"
>
<div
class=
"inline-flex !w-full companies-search-input"
>
<input
type=
"text"
class=
"form-control !rounded-e-none border-e-0"
aria-label=
"Text input with segmented dropdown button"
placeholder=
"ค้นหาจากข้อมูลพนักงาน"
[(
ngModel
)]="
searchTerm
"
>
<input
class=
"form-control"
id=
"daterange"
[(
ngModel
)]="
dateRange
"
placeholder=
"ช่วงวันที่"
mwlFlatpickr
[
altInput
]="
true
"
[
convertModelValue
]="
true
"
mode=
"range"
/>
<ng-select
class=
"form-control !rounded-none"
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
"พนักงาน"
[(
ngModel
)]="
empSelect
"
>
<ng-option
value=
""
>
ทั้งหมด
</ng-option>
@for(item of empList;track empList){
<ng-option
[
value
]="
item
.
company_employeeId
"
>
{{item.getFullname()}}
</ng-option>
}
</ng-select>
<ng-select
class=
"form-control !rounded-none"
name=
"choices-multiple-remove-button1"
id=
"choices-multiple-remove-button1"
placeholder=
"สถานะ"
[(
ngModel
)]="
statusSelect
"
>
<ng-option
value=
""
>
ทั้งหมด
</ng-option>
<ng-option
value=
"WARNING"
>
Warning
</ng-option>
<ng-option
value=
"CHECK_IN"
>
Complete
</ng-option>
<ng-option
value=
"DISAPPROVE"
>
Absent
</ng-option>
</ng-select>
<button
(
click
)="
getTimestamp
()"
type=
"button"
aria-label=
"button"
class=
"ti-btn ti-btn-primary-full !mb-0 !rounded-s-none"
><i
class=
"ri-search-line"
></i></button>
</div>
</div>
</div>
</div>
<div
class=
"xxl:col-span-8 xl:col-span-8 col-span-12"
>
<div
class=
"xxl:col-span-8 xl:col-span-12 lg:col-span-12 md:col-span-12 sm:col-span-12 col-span-12"
>
<ul
class=
"list-none mb-0 notification-container"
>
@for(item of filterList;track filterList){
<li>
<div
class=
"box border-s-[0.25rem] {{item.timestampType==0?'border-warning':''}} {{item.timestampType==1||item.timestampType==2?'border-success':''}} {{item.timestampType==3?'border-danger':''}}"
(
click
)="
view
(
item
)"
>
<div
class=
"box-body !p-4"
>
<a
href=
"javascript:void(0);"
>
<div
class=
"flex items-start mt-0 flex-wrap"
>
<span
class=
"avatar avatar-xl avatar-rounded"
>
<img
[
src
]="
item
.
getPicture
()"
alt=
""
>
</span>
<div
class=
"flex-grow"
>
<div
class=
"sm:flex items-center"
>
<div
class=
"sm:mt-0 mt-2 mx-2"
>
<p
class=
"font-semibold mb-0 flex items-center text-primary"
>
{{item.employee.member.firstName+ "
"+item.employee.member.lastName}}
</p>
<p
class=
"mb-0 text-secondary dark:text-white/50"
>
{{item.getLocation()}}
</p>
<p
class=
"mb-0 text-[#8c9097] dark:text-white/50"
><span
class=
"badge {{item.timestampType==0?'bg-warning':''}} {{item.timestampType==1||item.timestampType==2?'bg-success':''}} {{item.timestampType==3?'bg-danger':''}} text-white"
>
{{item.getStatus()}}
</span>
</p>
</div>
<div
class=
"ms-auto"
>
<h5
class=
"ltr:float-right rtl:float-left badge bg-light font-semibold text-primary dark:text-white whitespace-nowrap"
>
{{item.timestamp | date: "HH:mm"}} {{item.timestamp | date: "medium"}}
</h5>
</div>
</div>
</div>
</div>
</a>
</div>
</div>
</li>
}
</ul>
</div>
<ul
class=
"ti-pagination mb-4 justify-end"
>
<div
class=
"flex items-center flex-wrap overflow-auto"
*
ngIf=
"filterList.length > 0"
>
<div
class=
"mb-2 sm:mb-0"
>
<div>
{{'Showing' | translate}} {{filterList.length}} {{'entries'
| translate}}
<i
class=
"bi bi-arrow-right ms-2 font-semibold"
></i>
</div>
</div>
<div
class=
"ms-auto"
>
<nav
aria-label=
"Page navigation"
>
<ul
class=
"ti-pagination mb-0"
>
<li
*
ngIf=
"pageIndex>0"
class=
"page-item {{pageIndex==0 ? 'disabled' : ''}}"
><a
class=
"page-link px-3 py-[0.375rem]"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{'Previous'
| translate}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex-1>0"
(
click
)="
pageIndex =
pageIndex-2;updatePagedItems()"
>
{{pageIndex-1}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"pageIndex>0 && ((pageIndex-1)*10 < (searchTerm == '' ? itemsList.length : filterList.length))"
(
click
)="
pageIndex =
pageIndex-1;updatePagedItems()"
>
{{pageIndex}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link active px-3 py-[0.375rem]"
href=
"javascript:void(0);"
>
{{pageIndex +1}}
</a>
</li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{pageIndex +2}}
</a></li>
<li
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
href=
"javascript:void(0);"
*
ngIf=
"(pageIndex+2)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
(
click
)="
pageIndex =
pageIndex+2;updatePagedItems()"
>
{{pageIndex +3}}
</a></li>
<li
*
ngIf=
"(pageIndex+1)*10 < (searchTerm == '' ? itemsList.length : filterList.length)"
class=
"page-item"
><a
class=
"page-link px-3 py-[0.375rem]"
(
click
)="
pageIndex =
pageIndex+1;updatePagedItems()"
>
{{'Next' |
translate}}
</a>
</li>
</ul>
</nav>
</div>
</div>
</ul>
</div>
<div
class=
"xxl:col-span-4 xl:col-span-4 col-span-12"
*
ngIf=
"selectModel"
>
<div
class=
"box custom-box"
>
<div
class=
"box-header justify-between"
>
<div
class=
"box-title"
>
รายละเอียดการลงเวลา
</div>
<div>
</div>
</div>
<div
class=
"box-body !p-0"
>
<!-- <div class="box-body p-6">
<div class="text-center">
<span class="avatar avatar-xl avatar-rounded">
<img src="./assets/images/faces/2.jpg" alt="">
</span>
<div class="mt-2">
<p class="mb-0 font-semibold">Samantha May</p>
<p class="text-[0.75rem] opacity-[0.7] mb-1 text-[#8c9097] dark:text-white/50">
09:00</p>
<p class="mb-0 text-[#8c9097] dark:text-white/50"><span
class="badge bg-danger text-white">ลงเวลาผิดสถานที่</span></p>
</div>
</div>
</div>
<div class="box-footer text-center">
<div class="btn-list">
<button type="button" class="ti-btn btn-sm !py-1 !px-2 !text-[0.75rem] me-2 ti-btn-light">อนุมัติ</button>
<button type="button"
class="ti-btn btn-sm !py-1 !px-2 !text-[0.75rem] text-white bg-primary">ไม่อนุมัติ</button>
</div>
</div> -->
<div
class=
"box product-card"
>
<div
class=
"box-body"
>
<div
class=
"grid grid-cols-12 gap-6"
>
<div
class=
"xxl:col-span-6 xl:col-span-6 col-span-12"
>
<!-- <span class="avatar avatar-xl avatar-rounded">
<img [src]="item.getPicture()" alt="">
</span> -->
<img
src=
"{{selectModel.getPicture()}}"
class=
"card-img mb-3 avatar-rounded"
alt=
"..."
>
</div>
<div
class=
"xxl:col-span-6 xl:col-span-6 col-span-12"
>
<div
class=
"flex-grow"
>
<div
class=
"sm:flex items-center"
>
<div
class=
"sm:mt-0 mt-2 mx-2"
>
<p
class=
"font-semibold mb-0 flex items-center text-primary"
>
{{selectModel.employee.member.firstName+ "
"+selectModel.employee.member.lastName}}
</p>
<p
class=
"mb-0 text-secondary dark:text-white/50"
>
{{selectModel.latitude}} ,
{{selectModel.longitude}}
</p>
<p
class=
"mb-0 text-[#8c9097] dark:text-white/50"
><span
class=
"badge {{selectModel.timestampType==0?'bg-warning':''}} {{selectModel.timestampType==1||selectModel.timestampType==2?'bg-success':''}} {{selectModel.timestampType==3?'bg-danger':''}} text-white"
>
{{selectModel.getStatus()}}
</span>
</p>
</div>
<div
class=
"ms-auto"
>
<h5
class=
"ltr:float-right rtl:float-left badge bg-light font-semibold text-primary dark:text-white whitespace-nowrap"
>
{{selectModel.timestamp | date: "HH:mm"}} {{selectModel.timestamp | date: "medium"}}
</h5>
</div>
</div>
</div>
<input
type=
"text"
class=
"form-control !rounded-e-none border-e-0 mt-5"
aria-label=
"Text input with segmented dropdown button"
placeholder=
"ชื่อสถานที่"
[(
ngModel
)]="
selectModel
.
locationName
"
[
disabled
]="
selectModel
.
timestampType
!=
0
"
>
<a
*
ngIf=
"selectModel.timestampType==0"
(
click
)="
approveTime
(
selectModel
)"
class=
"ti-btn ti-btn-primary m-1 !me-2 !font-medium"
><i
class=
"ri-check-line me-1 align-middle"
></i>
อนุมัติ
</a>
<a
*
ngIf=
"selectModel.timestampType==0"
(
click
)="
disapproveTime
(
selectModel
)"
class=
"ti-btn ti-btn-success m-1 !font-medium"
><i
class=
"ri-close-line me-1 align-middle"
></i>
ไม่อนุมัติ
</a>
</div>
<div
class=
"xxl:col-span-12 xl:col-span-12 col-span-12"
>
<google-map
height=
"400px"
[
center
]="{
lat:
selectModel
.
latitude
,
lng:
selectModel
.
longitude
}"
[
zoom
]="
12
"
>
<map-marker
#
mapMarker=
"mapMarker"
[
position
]="{
lat:
selectModel
.
latitude
,
lng:
selectModel
.
longitude
}"
[
options
]="
markerOptions
"
/>
</google-map>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--End::row-1 -->
src/app/portal-manage/company-management/timestamp-log/timestamp-log.component.spec.ts
deleted
100644 → 0
View file @
8b2e4a55
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
TimestampLogComponent
}
from
'./timestamp-log.component'
;
describe
(
'TimestampLogComponent'
,
()
=>
{
let
component
:
TimestampLogComponent
;
let
fixture
:
ComponentFixture
<
TimestampLogComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
TimestampLogComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
TimestampLogComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/portal-manage/company-management/timestamp-log/timestamp-log.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
Component
,
ElementRef
,
ViewChild
,
ViewEncapsulation
}
from
'@angular/core'
;
import
{
SharedModule
}
from
'../../../shared/shared.module'
;
import
{
SimplebarAngularModule
}
from
'simplebar-angular'
;
import
{
MaterialModuleModule
}
from
'../../../material-module/material-module.module'
;
import
{
ActivatedRoute
,
RouterModule
}
from
'@angular/router'
;
import
{
NgSelectModule
}
from
'@ng-select/ng-select'
;
import
{
FlatpickrDefaults
,
FlatpickrModule
}
from
'angularx-flatpickr'
;
import
{
MatDatepickerModule
}
from
'@angular/material/datepicker'
;
import
{
TimestampService
}
from
'../../services/timestamp.service'
;
import
{
TranslateModule
,
TranslateService
}
from
'@ngx-translate/core'
;
import
{
TokenService
}
from
'../../../shared/services/token.service'
;
import
{
TimestampModel
}
from
'../../models/timestamp.model'
;
import
swal
from
'sweetalert'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
FormsModule
}
from
'@angular/forms'
;
import
moment
from
'moment'
;
import
{
EmployeeModel
}
from
'../../models/employee.model'
;
import
{
EmployeeService
}
from
'../../services/employee.service'
;
import
{
GoogleMapsModule
,
MapMarker
}
from
'@angular/google-maps'
;
@
Component
({
selector
:
'app-timestamp-log'
,
templateUrl
:
'./timestamp-log.component.html'
,
standalone
:
true
,
imports
:
[
CommonModule
,
SharedModule
,
TranslateModule
,
NgSelectModule
,
FormsModule
,
GoogleMapsModule
,
MapMarker
,
RouterModule
,
FlatpickrModule
],
styleUrls
:
[
'./timestamp-log.component.css'
],
providers
:
[
FlatpickrDefaults
],
encapsulation
:
ViewEncapsulation
.
None
})
export
class
TimestampLogComponent
{
public
dateRange
:
{
from
:
Date
,
to
:
Date
}
=
{
from
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
(),
1
),
to
:
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
()
+
1
,
0
)
};
public
options
:
any
=
{
"autoApply"
:
true
,
ranges
:
this
.
translate
.
currentLang
==
'th'
?
{
'วันนี้'
:
[
moment
(),
moment
()],
'7 วันล่าสุด'
:
[
moment
().
subtract
(
6
,
'days'
),
moment
()],
'30 วันล่าสุด'
:
[
moment
().
subtract
(
29
,
'days'
),
moment
()],
'เดือนนี้'
:
[
moment
().
startOf
(
'month'
),
moment
().
endOf
(
'month'
)]
}
:
{
'Today'
:
[
moment
(),
moment
()],
'Last 7 Days'
:
[
moment
().
subtract
(
6
,
'days'
),
moment
()],
'Last 30 Days'
:
[
moment
().
subtract
(
29
,
'days'
),
moment
()],
'This Month'
:
[
moment
().
startOf
(
'month'
),
moment
().
endOf
(
'month'
)]
},
"locale"
:
{
"format"
:
"DD/MM/YYYY"
,
"separator"
:
" - "
,
"applyLabel"
:
"ตกลง"
,
"cancelLabel"
:
"ยกเลิก"
,
"fromLabel"
:
"จาก"
,
"toLabel"
:
"ถึง"
,
"daysOfWeek"
:
this
.
translate
.
instant
(
"NameDayShort"
),
"monthNames"
:
this
.
translate
.
instant
(
"NameMonth"
),
"customRangeLabel"
:
this
.
translate
.
instant
(
"Range date"
),
"firstDay"
:
1
,
direction
:
'daterange-center shadow'
},
"alwaysShowCalendars"
:
true
,
"startDate"
:
this
.
dateRange
.
from
,
"endDate"
:
this
.
dateRange
.
to
,
};
@
ViewChild
(
'closeModal'
)
public
childModal
?:
ElementRef
;
@
ViewChild
(
'modalDetail'
)
public
modalDetail
?:
ElementRef
;
action
=
"new"
;
allSelected
=
false
;
someSelected
=
false
;
itemsList
:
TimestampModel
[]
=
[]
filterList
:
TimestampModel
[]
=
[]
selectModel
?:
TimestampModel
empList
:
EmployeeModel
[]
=
[]
empSelect
=
""
statusSelect
=
""
descName
=
'engName'
pageIndex
=
0
;
center
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
zoom
=
5
;
markerOptions
:
google
.
maps
.
MarkerOptions
=
{
draggable
:
false
};
markerPositions
:
google
.
maps
.
LatLngLiteral
=
{
lat
:
13.7563
,
lng
:
100.5018
};
get
searchTerm
():
string
{
return
this
.
_searchTerm
;
}
set
searchTerm
(
val
:
string
)
{
this
.
pageIndex
=
0
;
this
.
allSelected
=
false
this
.
_searchTerm
=
val
;
if
(
val
!=
''
)
{
this
.
filterList
=
this
.
filter
(
val
);
}
else
{
this
.
updatePagedItems
()
}
}
_searchTerm
=
""
;
companyId
=
""
constructor
(
private
timeService
:
TimestampService
,
public
translate
:
TranslateService
,
private
tokenService
:
TokenService
,
private
employeeService
:
EmployeeService
,
private
route
:
ActivatedRoute
)
{
this
.
empSelect
=
this
.
route
.
snapshot
.
paramMap
.
get
(
'company_employeeId'
)
||
""
;
this
.
companyId
=
this
.
tokenService
.
getSelectCompany
().
companyId
;;
this
.
getTimestamp
()
this
.
getEmp
()
}
ngOnInit
():
void
{
}
getTimestamp
()
{
this
.
pageIndex
=
0
;
console
.
log
(
this
.
dateRange
)
this
.
timeService
.
getListsSearch
(
this
.
tokenService
.
getSelectCompany
().
companyId
,
this
.
empSelect
,
new
Date
(
this
.
dateRange
.
from
).
toISOString
(),
new
Date
(
this
.
dateRange
.
to
).
toISOString
(),
this
.
statusSelect
).
subscribe
(
result
=>
{
this
.
itemsList
=
result
.
sort
((
a
,
b
)
=>
b
.
timestamp
.
localeCompare
(
a
.
timestamp
));
this
.
updatePagedItems
()
})
}
getEmp
()
{
this
.
employeeService
.
getLists
(
this
.
companyId
).
subscribe
(
result
=>
{
this
.
empList
=
result
})
}
searchTime
()
{
console
.
log
(
this
.
dateRange
)
}
filter
(
v
:
string
)
{
return
this
.
itemsList
?.
filter
(
(
x
)
=>
x
.
company_employeeId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
timestampId
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
timestamp
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
locationName
?.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
getStatus
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
timestamp
.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
employee
.
getFullname
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
employee
.
position
.
getName
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
employee
.
department
.
getName
().
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
||
x
.
employee
.
employeeId
.
toLowerCase
().
indexOf
(
v
.
toLowerCase
())
!==
-
1
);
}
delete
(
item
:
TimestampModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"You won't be able to revert this!"
,
icon
:
"warning"
,
dangerMode
:
true
,
buttons
:
[
"Cancel"
,
"Yes,Delete it!"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
this
.
timeService
.
delete
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getTimestamp
()
})
}
});
}
new
()
{
this
.
action
=
'add'
this
.
selectModel
=
new
TimestampModel
()
this
.
selectModel
.
latitude
=
0.00
this
.
selectModel
.
longitude
=
0.00
}
view
(
item
:
TimestampModel
)
{
this
.
action
=
'edit'
this
.
selectModel
=
new
TimestampModel
(
item
,
this
.
translate
)
console
.
log
(
this
.
selectModel
)
}
approveTime
(
item
:
TimestampModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
item
.
timestampType
=
1
;
this
.
timeService
.
update
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
selectModel
=
undefined
this
.
getTimestamp
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
});
}
disapproveTime
(
item
:
TimestampModel
)
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
item
.
timestampType
=
3
;
this
.
timeService
.
update
(
this
.
companyId
,
item
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
selectModel
=
undefined
this
.
getTimestamp
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
});
}
save
()
{
swal
({
title
:
"Are you sure?"
,
text
:
"คุณต้องการบันทึกหรือไม่"
,
icon
:
"warning"
,
dangerMode
:
false
,
buttons
:
[
"Cancel"
,
"Confirm"
],
})
.
then
((
willDelete
:
any
)
=>
{
if
(
willDelete
)
{
if
(
this
.
action
==
'add'
)
{
this
.
timeService
.
save
(
this
.
companyId
,
this
.
selectModel
!
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getTimestamp
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
else
if
(
this
.
action
==
'edit'
)
{
this
.
timeService
.
update
(
this
.
companyId
,
this
.
selectModel
!
).
subscribe
(
result
=>
{
console
.
log
(
result
)
swal
(
"Save Success!!"
,
"บันทึกข้อมูลสำเร็จ"
,
"success"
);
this
.
getTimestamp
()
this
.
childModal
?.
nativeElement
.
click
()
})
}
}
});
}
updatePagedItems
()
{
const
startIndex
=
this
.
pageIndex
*
10
;
const
endIndex
=
startIndex
+
10
;
this
.
filterList
=
this
.
itemsList
.
slice
(
startIndex
,
endIndex
);
}
}
src/app/portal-manage/company-management/warning-timetamp/warning-timetamp.component.css
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/company-management/warning-timetamp/warning-timetamp.component.html
deleted
100644 → 0
View file @
8b2e4a55
<p>
warning-timetamp works!
</p>
src/app/portal-manage/company-management/warning-timetamp/warning-timetamp.component.spec.ts
deleted
100644 → 0
View file @
8b2e4a55
/* tslint:disable:no-unused-variable */
import
{
async
,
ComponentFixture
,
TestBed
}
from
'@angular/core/testing'
;
import
{
By
}
from
'@angular/platform-browser'
;
import
{
DebugElement
}
from
'@angular/core'
;
import
{
WarningTimetampComponent
}
from
'./warning-timetamp.component'
;
describe
(
'WarningTimetampComponent'
,
()
=>
{
let
component
:
WarningTimetampComponent
;
let
fixture
:
ComponentFixture
<
WarningTimetampComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
WarningTimetampComponent
]
})
.
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
WarningTimetampComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'should create'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
src/app/portal-manage/company-management/warning-timetamp/warning-timetamp.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
Component
,
OnInit
}
from
'@angular/core'
;
@
Component
({
selector
:
'app-warning-timetamp'
,
templateUrl
:
'./warning-timetamp.component.html'
,
standalone
:
true
,
styleUrls
:
[
'./warning-timetamp.component.css'
]
})
export
class
WarningTimetampComponent
implements
OnInit
{
constructor
()
{
}
ngOnInit
()
{
}
}
src/app/portal-manage/home/home.component.ts
View file @
27f02f55
...
@@ -285,18 +285,7 @@ export class HomeComponent implements OnInit {
...
@@ -285,18 +285,7 @@ export class HomeComponent implements OnInit {
category
:
'applications'
,
category
:
'applications'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
},
// การบริการ
{
id
:
'dashboard'
,
name
:
'dashboard'
,
displayName
:
'Dashboard'
,
description
:
'แดชบอร์ดหลัก'
,
icon
:
'./assets/images/icons/dashboard.png'
,
path
:
'/portal-manage/dashboard'
,
isVisible
:
true
,
category
:
'services'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
{
id
:
'meetingBooking'
,
id
:
'meetingBooking'
,
name
:
'meeting-booking'
,
name
:
'meeting-booking'
,
...
@@ -320,66 +309,13 @@ export class HomeComponent implements OnInit {
...
@@ -320,66 +309,13 @@ export class HomeComponent implements OnInit {
category
:
'system'
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
},
{
id
:
'roleManagement'
,
name
:
'role-management'
,
displayName
:
'Role Management'
,
description
:
'ระบบจัดการบทบาท'
,
icon
:
'./assets/images/icons/users.png'
,
path
:
'/portal-manage/role-management'
,
isVisible
:
true
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
id
:
'menuPermissionManagement'
,
name
:
'menu-permission-management'
,
displayName
:
'Menu Permission'
,
description
:
'ระบบจัดการสิทธิ์เมนู'
,
icon
:
'./assets/images/icons/menu.png'
,
path
:
'/portal-manage/menu-permission-management'
,
isVisible
:
true
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
id
:
'userManagement'
,
name
:
'user-role-management'
,
displayName
:
'User & Role Management'
,
description
:
'ระบบจัดการผู้ใช้และบทบาท'
,
icon
:
'./assets/images/icons/users.png'
,
path
:
'/portal-manage/user-role-management'
,
isVisible
:
true
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
id
:
'companyManagement'
,
name
:
'company-management'
,
displayName
:
'Company Management'
,
description
:
'ระบบจัดการบริษัท'
,
icon
:
'./assets/images/icons/building.png'
,
path
:
'/portal-manage/company-management'
,
isVisible
:
true
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
id
:
'widgetManagement'
,
name
:
'widget-management'
,
displayName
:
'Widget Management'
,
description
:
'ระบบจัดการวิดเจ็ต'
,
icon
:
'./assets/images/icons/widget.png'
,
path
:
'/portal-manage/widget-management'
,
isVisible
:
true
,
category
:
'system'
,
permissions
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
,
import
:
true
}
},
{
{
id
:
'dashboardManagement'
,
id
:
'dashboardManagement'
,
name
:
'dashboard-management'
,
name
:
'dashboard-management'
,
displayName
:
'Dashboard Management'
,
displayName
:
'Dashboard Management'
,
description
:
'ระบบจัดการแดชบอร์ด'
,
description
:
'ระบบจัดการแดชบอร์ด
และคลังวิดเจ็ต
'
,
icon
:
'./assets/images/icons/dashboard.png'
,
icon
:
'./assets/images/icons/dashboard.png'
,
path
:
'/portal-manage/dashboard-management'
,
path
:
'/portal-manage/dashboard-management'
,
isVisible
:
true
,
isVisible
:
true
,
...
...
src/app/portal-manage/portal-manage.routes.ts
View file @
27f02f55
...
@@ -95,13 +95,6 @@ export const portalManageRoutes: Routes = [
...
@@ -95,13 +95,6 @@ export const portalManageRoutes: Routes = [
canActivate
:
[
moduleAccessGuard
]
canActivate
:
[
moduleAccessGuard
]
},
},
// Company Management
{
path
:
'company-management'
,
canActivate
:
[
moduleAccessGuard
],
loadChildren
:
()
=>
import
(
'./company-management/company-management.module'
).
then
(
m
=>
m
.
CompanyManagementModule
)
},
// Widget Management
// Widget Management
{
{
path
:
'widget-management'
,
path
:
'widget-management'
,
...
...
src/app/portal-manage/widget-stock/widget-stock.component.html
deleted
100644 → 0
View file @
8b2e4a55
src/app/portal-manage/widget-stock/widget-stock.component.scss
deleted
100644 → 0
View file @
8b2e4a55
/* Add custom styles for your widget stock component here */
src/app/portal-manage/widget-stock/widget-stock.component.ts
deleted
100644 → 0
View file @
8b2e4a55
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
Observable
}
from
'rxjs'
;
import
{
IWidget
}
from
'../../shared/models/dashboard.model'
;
import
{
DashboardService
}
from
'../../shared/services/dashboard.service'
;
@
Component
({
selector
:
'app-widget-stock'
,
standalone
:
true
,
imports
:
[
CommonModule
],
templateUrl
:
'./widget-stock.component.html'
,
styleUrls
:
[
'./widget-stock.component.scss'
]
})
export
class
WidgetStockComponent
implements
OnInit
{
public
availableWidgets$
!
:
Observable
<
IWidget
[]
>
;
constructor
(
private
dashboardService
:
DashboardService
)
{
}
ngOnInit
():
void
{
this
.
availableWidgets$
=
this
.
dashboardService
.
getAvailableWidgets
();
}
}
src/app/shared/components/header/header.component.html
View file @
27f02f55
...
@@ -451,6 +451,15 @@
...
@@ -451,6 +451,15 @@
</a>
</a>
</div>
</div>
<div
class=
""
>
<a
routerLink=
"/portal-manage/widget-stock"
class=
"p-4 items-center related-app block text-center rounded-sm hover:bg-gray-50 dark:hover:bg-black/20"
>
<img
src=
"./assets/images/icons/widget.png"
alt=
"Widget Stock"
class=
"leading-[1.75] text-2xl !h-[1.75rem] align-middle flex justify-center mx-auto"
>
<div
class=
"text-[0.75rem] text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50 mt-1"
>
Widget Stock
</div>
</a>
</div>
</div>
</div>
</div>
</div>
...
...
src/app/shared/routes/content.routes.ts
View file @
27f02f55
...
@@ -14,7 +14,6 @@ import { formsRoutingModule } from '../../components/forms/forms.routes';
...
@@ -14,7 +14,6 @@ import { formsRoutingModule } from '../../components/forms/forms.routes';
import
{
mapsRoutingModule
}
from
'../../components/maps/maps.routes'
;
import
{
mapsRoutingModule
}
from
'../../components/maps/maps.routes'
;
import
{
iconsRoutingModule
}
from
'../../components/icons/icons.routes'
;
import
{
iconsRoutingModule
}
from
'../../components/icons/icons.routes'
;
import
{
tablesRoutingModule
}
from
'../../components/tables/tables.routes'
;
import
{
tablesRoutingModule
}
from
'../../components/tables/tables.routes'
;
import
{
CompanyManagementModule
}
from
'../../portal-manage/company-management/company-management.module'
;
import
{
MyskillXModule
}
from
'../../portal-manage/myskill-x/myskill-x.module'
;
import
{
MyskillXModule
}
from
'../../portal-manage/myskill-x/myskill-x.module'
;
import
{
MylearnModule
}
from
'../../portal-manage/mylearn/mylearn.module'
;
import
{
MylearnModule
}
from
'../../portal-manage/mylearn/mylearn.module'
;
import
{
MyjobModule
}
from
'../../portal-manage/myjob/myjob.module'
;
import
{
MyjobModule
}
from
'../../portal-manage/myjob/myjob.module'
;
...
@@ -43,7 +42,6 @@ export const content: Routes = [
...
@@ -43,7 +42,6 @@ export const content: Routes = [
...
mapsRoutingModule
.
routes
,
...
mapsRoutingModule
.
routes
,
...
iconsRoutingModule
.
routes
,
...
iconsRoutingModule
.
routes
,
...
tablesRoutingModule
.
routes
,
...
tablesRoutingModule
.
routes
,
...
CompanyManagementModule
.
routes
,
...
MyskillXModule
.
routes
,
...
MyskillXModule
.
routes
,
...
MylearnModule
.
routes
,
...
MylearnModule
.
routes
,
...
MyjobModule
.
routes
,
...
MyjobModule
.
routes
,
...
...
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