Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mySkill-x
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
mySkill-x
Commits
5d5f9cd4
Commit
5d5f9cd4
authored
Aug 18, 2025
by
Nattana Chaiyamat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ทะเบียนหลักสูตร
parent
b0814b9d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
280 additions
and
15 deletions
+280
-15
development-course.component.html
...tion/development-course/development-course.component.html
+17
-13
development-course.component.ts
...ration/development-course/development-course.component.ts
+1
-1
dashboard.module.ts
src/app/components/dashboard/dashboard.module.ts
+3
-1
money-input.directive.ts
...app/shared/directive/money-input/money-input.directive.ts
+249
-0
competency-course.model.ts
src/app/shared/model/competency-course.model.ts
+10
-0
No files found.
src/app/components/competency-assessment/course-registration/development-course/development-course.component.html
View file @
5d5f9cd4
...
...
@@ -82,22 +82,25 @@
<input
type=
"text"
id=
"detail_th"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
tdesc
"
>
<label
for=
"detail_eng"
class=
"ti-form-label mt-2rem"
>
ชื่อหลักสูตร (อังกฤษ)
</label>
<input
type=
"text"
id=
"detail_eng"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
edesc
"
>
<label
for=
"
detail_eng
"
class=
"ti-form-label mt-2rem"
>
วัตถุประสงค์
</label>
<textarea
type=
"text"
id=
"
detail_eng
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
<label
for=
"
courseDetail
"
class=
"ti-form-label mt-2rem"
>
วัตถุประสงค์
</label>
<textarea
type=
"text"
id=
"
courseDetail
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
[(
ngModel
)]="
competencyCourse
.
select
.
courseDetail
"
>
</textarea>
<label
for=
"
detail_eng
"
class=
"ti-form-label mt-2rem"
>
หัวข้อเรื่อง
</label>
<textarea
type=
"text"
id=
"
detail_eng
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
<label
for=
"
courseTopic
"
class=
"ti-form-label mt-2rem"
>
หัวข้อเรื่อง
</label>
<textarea
type=
"text"
id=
"
courseTopic
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
[(
ngModel
)]="
competencyCourse
.
select
.
courseTopic
"
>
</textarea>
<label
for=
"detail_eng
"
class=
"ti-form-label mt-2rem"
>
วิธีการ
</label>
<textarea
type=
"text"
id=
"
detail_eng
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
<label
for=
"proceDure
"
class=
"ti-form-label mt-2rem"
>
วิธีการ
</label>
<textarea
type=
"text"
id=
"
proceDure
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
[(
ngModel
)]="
competencyCourse
.
select
.
proceDure
"
>
</textarea>
<label
for=
"detail_eng
"
class=
"ti-form-label mt-2rem"
>
คุณสมบัติผู้เข้าร่วม
</label>
<textarea
type=
"text"
id=
"
detail_eng
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
<label
for=
"propertyUser
"
class=
"ti-form-label mt-2rem"
>
คุณสมบัติผู้เข้าร่วม
</label>
<textarea
type=
"text"
id=
"
propertyUser
"
class=
"ti-form-input"
rows=
"4"
cols=
"50"
[(
ngModel
)]="
competencyCourse
.
select
.
propertyUser
"
>
</textarea>
<label
for=
"detail_eng"
class=
"ti-form-label mt-2rem"
>
ผู้สอน/วิทยากร
</label>
<input
type=
"text"
id=
"detail_eng"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
lecTurers
"
>
<label
for=
"detail_eng"
class=
"ti-form-label mt-2rem"
>
ระยะเวลา
</label>
<input
type=
"text"
id=
"detail_eng"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
timeLine
"
>
<label
for=
"lecTurers"
class=
"ti-form-label mt-2rem"
>
ผู้สอน/วิทยากร
</label>
<input
type=
"text"
id=
"lecTurers"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
lecTurers
"
>
<label
for=
"timeLine"
class=
"ti-form-label mt-2rem"
>
ระยะเวลา
</label>
<input
type=
"text"
id=
"timeLine"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
timeLine
"
>
<label
for=
"expenses"
class=
"ti-form-label mt-2rem"
>
ค่าใช้จ่าย
</label>
<input
type=
"text"
id=
"expenses"
class=
"ti-form-input h-10"
appMoneyInput
[(
ngModel
)]="
competencyCourse
.
select
.
expenses
"
>
<label
class=
"ti-form-label mt-2rem"
>
Link myLearn
</label>
<input
type=
"text"
class=
"ti-form-input h-10"
[(
ngModel
)]="
competencyCourse
.
select
.
courseLinkMylearn
"
>
</mat-dialog-content>
...
...
@@ -149,4 +152,4 @@
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
src/app/components/competency-assessment/course-registration/development-course/development-course.component.ts
View file @
5d5f9cd4
...
...
@@ -146,7 +146,7 @@ export class DevelopmentCourseComponent {
}).
then
((
result
)
=>
{
if
(
result
.
isConfirmed
)
{
this
.
competencyCourse
.
loading
=
true
this
.
competencycourseService
.
post
(
this
.
competencyCourse
.
select
).
subscribe
({
this
.
competencycourseService
.
post
(
new
MyCompetencyCourseModel
(
this
.
competencyCourse
.
select
)
).
subscribe
({
next
:
response
=>
{
if
(
response
.
success
)
{
this
.
showAlert
(
response
.
message
,
'success'
)
...
...
src/app/components/dashboard/dashboard.module.ts
View file @
5d5f9cd4
...
...
@@ -207,6 +207,7 @@ import {
import
{
SettingIndividualKpiComponent
}
from
'../setting-individual-kpi/setting-individual-kpi.component'
;
import
{
SettingIndividualKpiSupervisorComponent
}
from
'../setting-individual-kpi-supervisor/setting-individual-kpi-supervisor.component'
;
import
{
JobDescriptionEssComponent
}
from
'../job-description-ess/job-description-ess.component'
;
import
{
MoneyInputDirective
}
from
'src/app/shared/directive/money-input/money-input.directive'
;
export
const
MY_DATE_FORMATS
=
{
parse
:
{
...
...
@@ -355,7 +356,8 @@ export class CustomDateAdapter extends NativeDateAdapter {
PivotSyncfutionComponent
,
SettingIndividualKpiComponent
,
SettingIndividualKpiSupervisorComponent
,
JobDescriptionEssComponent
JobDescriptionEssComponent
,
MoneyInputDirective
],
imports
:
[
CommonModule
,
...
...
src/app/shared/directive/money-input/money-input.directive.ts
0 → 100644
View file @
5d5f9cd4
import
{
Directive
,
ElementRef
,
HostListener
,
Input
,
OnChanges
,
Optional
,
SimpleChanges
}
from
'@angular/core'
;
import
{
NgControl
}
from
'@angular/forms'
;
@
Directive
({
selector
:
'[appMoneyInput]'
})
export
class
MoneyInputDirective
{
@
Input
()
allowEmpty
:
boolean
=
false
;
constructor
(
private
el
:
ElementRef
<
HTMLInputElement
>
)
{
}
ngAfterViewInit
()
{
setTimeout
(()
=>
{
this
.
formatValue
(
this
.
el
.
nativeElement
.
value
);
this
.
onBlur
()
});
}
@
HostListener
(
'input'
,
[
'$event.target.value'
])
onInput
(
value
:
string
)
{
this
.
formatValue
(
value
);
}
@
HostListener
(
'blur'
)
onBlur
()
{
let
val
=
this
.
el
.
nativeElement
.
value
.
replace
(
/,/g
,
''
);
if
(
!
val
)
return
;
let
num
=
parseFloat
(
val
);
if
(
isNaN
(
num
))
return
;
let
parts
=
num
.
toFixed
(
2
).
split
(
'.'
);
let
intPart
=
parts
[
0
].
replace
(
/
\B(?=(\d{3})
+
(?!\d))
/g
,
','
);
this
.
el
.
nativeElement
.
value
=
`
${
intPart
}
.
${
parts
[
1
]}
`
;
}
formatValue
(
value
:
string
)
{
let
cleaned
=
value
.
replace
(
/
[^
0-9.
]
/g
,
''
).
replace
(
/^0+/
,
''
);
const
dotIndex
=
cleaned
.
indexOf
(
'.'
);
if
(
dotIndex
==
0
)
{
cleaned
=
`0.`
;
}
else
if
(
dotIndex
!==
-
1
)
{
const
beforeDot
=
cleaned
.
slice
(
0
,
dotIndex
);
let
afterDot
=
cleaned
.
slice
(
dotIndex
+
1
).
replace
(
/
\.
/g
,
''
);
afterDot
=
afterDot
.
substring
(
0
,
2
);
// หลังจุด 2 ตัว
cleaned
=
`
${
beforeDot
}
.
${
afterDot
}
`
;
}
if
(
!
this
.
allowEmpty
&&
cleaned
==
''
)
{
cleaned
=
'0'
}
let
[
intPart
,
decimalPart
]
=
cleaned
.
split
(
'.'
);
intPart
=
intPart
.
replace
(
/
\B(?=(\d{3})
+
(?!\d))
/g
,
','
);
this
.
el
.
nativeElement
.
value
=
decimalPart
!==
undefined
?
`
${
intPart
}
.
${
decimalPart
}
`
:
intPart
;
}
}
// import {
// Directive,
// ElementRef,
// HostListener,
// Input,
// OnChanges,
// Optional,
// SimpleChanges
// } from '@angular/core';
// import { NgControl } from '@angular/forms';
// @Directive({
// selector: '[appMoneyInput]'
// })
// export class MoneyInputDirective implements OnChanges {
// @Input() min?: string | number;
// @Input() max?: string | number;
// @Input() allowEmpty: boolean = false;
// @Input() defaultValue: number | string = 0;
// @Input() clearZeroOnFocus: boolean = false;
// private hasChanged = false
// private minValue?: number;
// private maxValue?: number;
// constructor(private el: ElementRef, @Optional() private control: NgControl) { }
// ngOnInit() {
// // แสดง defaultValue ตั้งแต่เข้าหน้า
// if (!this.allowEmpty) {
// const defaultNum = this.parseToNumber(this.defaultValue) ?? 0;
// const formatted = this.formatNumber(defaultNum);
// this.el.nativeElement.value = formatted;
// this.control?.control?.setValue(formatted);
// }
// }
// ngOnChanges(changes: SimpleChanges) {
// if ('min' in changes) {
// this.minValue = this.parseToNumber(this.min);
// }
// if ('max' in changes) {
// this.maxValue = this.parseToNumber(this.max);
// }
// }
// @HostListener('keydown', ['$event'])
// onKeyDown(event: KeyboardEvent) {
// if (event.key === ',' || event.key === 'Comma') {
// event.preventDefault();
// }
// }
// @HostListener('input', ['$event.target'])
// onInput(target: HTMLInputElement) {
// this.hasChanged = true
// let value = target.value;
// const endsWithDot = value.endsWith('.') && (value.match(/\./g) || []).length === 1;
// // เอาเฉพาะตัวเลขกับจุด
// let cleaned = '';
// let dotSeen = false;
// for (const char of value) {
// if (char >= '0' && char <= '9') {
// cleaned += char;
// } else if (char === '.' && !dotSeen) {
// cleaned += char;
// dotSeen = true;
// }
// }
// if (cleaned.startsWith('.')) {
// cleaned = '0' + cleaned;
// }
// const parts = cleaned.split('.');
// let intPart = parts[0].replace(/^0+/, '') || '0';
// let decimalPart = parts[1] || '';
// decimalPart = decimalPart.substring(0, 2);
// intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// let formatted = decimalPart ? `${intPart}.${decimalPart}` : intPart;
// if (endsWithDot && decimalPart.length === 0) {
// formatted += '.';
// }
// const numericValue = parseFloat(cleaned);
// if (!isNaN(numericValue)) {
// if (this.minValue !== undefined && numericValue < this.minValue) {
// formatted = this.formatNumber(this.minValue);
// }
// if (this.maxValue !== undefined && numericValue > this.maxValue) {
// formatted = this.formatNumber(this.maxValue);
// }
// }
// // ลบจนว่างได้ ถ้า allowEmpty
// if (cleaned === '' && this.allowEmpty) {
// formatted = '';
// }
// this.el.nativeElement.value = formatted;
// this.control?.control?.setValue(formatted);
// setTimeout(() => {
// const pos = this.el.nativeElement.value.length;
// this.el.nativeElement.setSelectionRange(pos, pos);
// }, 0);
// }
// @HostListener('focus')
// onFocus() {
// if (!this.clearZeroOnFocus) return;
// const value = this.el.nativeElement.value.replace(/,/g, '');
// if (value === '0' || value === '0.00') {
// this.el.nativeElement.value = '';
// this.control?.control?.setValue('');
// }
// }
// @HostListener('blur')
// onBlur() {
// let value = this.el.nativeElement.value;
// const raw = value.replace(/,/g, '');
// // ถ้าช่องว่างหรือไม่ใช่ตัวเลข → ใช้ defaultValue
// if (!raw || isNaN(parseFloat(raw))) {
// if (!this.allowEmpty) {
// const defaultNum = this.parseToNumber(this.defaultValue);
// const formatted = this.formatNumber(defaultNum ?? 0);
// this.el.nativeElement.value = formatted;
// this.control?.control?.setValue(formatted);
// }
// this.hasChanged = false;
// return;
// }
// if (!this.hasChanged) return;
// const parts = raw.split('.');
// let intPart = parts[0].replace(/^0+/, '') || '0';
// let decimalPart = parts[1] || '';
// if (decimalPart.length === 0) {
// decimalPart = '00';
// } else if (decimalPart.length === 1) {
// decimalPart += '0';
// } else {
// decimalPart = decimalPart.substring(0, 2);
// }
// intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// const formatted = `${intPart}.${decimalPart}`;
// this.el.nativeElement.value = formatted;
// this.control?.control?.setValue(formatted);
// this.hasChanged = false;
// }
// private parseToNumber(value: string | number | undefined): number | undefined {
// if (value === undefined || value === null) return undefined;
// if (typeof value === 'number') return value;
// const clean = value.replace(/,/g, '');
// const num = parseFloat(clean);
// return isNaN(num) ? undefined : num;
// }
// private formatNumber(value: number): string {
// const parts = value.toFixed(2).split('.');
// const intPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// const decimalPart = parts[1];
// return `${intPart}.${decimalPart}`;
// }
// }
src/app/shared/model/competency-course.model.ts
View file @
5d5f9cd4
...
...
@@ -10,6 +10,7 @@ export interface CompetencyCourseModel {
propertyUser
:
string
lecTurers
:
string
timeLine
:
string
expenses
:
number
}
export
class
MyCompetencyCourseModel
implements
CompetencyCourseModel
{
competencyCourseId
:
string
...
...
@@ -23,6 +24,7 @@ export class MyCompetencyCourseModel implements CompetencyCourseModel {
propertyUser
:
string
lecTurers
:
string
timeLine
:
string
expenses
:
number
constructor
(
data
?:
Partial
<
CompetencyCourseModel
>
)
{
this
.
competencyCourseId
=
data
?.
competencyCourseId
||
""
this
.
tdesc
=
data
?.
tdesc
||
""
...
...
@@ -35,6 +37,14 @@ export class MyCompetencyCourseModel implements CompetencyCourseModel {
this
.
propertyUser
=
data
?.
propertyUser
||
""
this
.
lecTurers
=
data
?.
lecTurers
||
""
this
.
timeLine
=
data
?.
timeLine
||
""
this
.
expenses
=
this
.
toNumber
(
data
?.
expenses
+
''
)
}
toNumber
(
value
:
string
):
number
{
if
(
!
value
)
return
0
const
cleaned
=
value
.
replace
(
/
[^\d
.-
]
/g
,
''
)
const
num
=
parseFloat
(
cleaned
)
return
isNaN
(
num
)
?
0
:
num
}
}
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