Commit 3f5b4d85 by Nattana Chaiyamat

เพิ่มหน้าจอ สำหรับ Module one X ทั้งหมด 11หน้า

parent 528b4d5d
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Career Path Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture3.png" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Career Path </h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-3" style="margin-top: 4rem">
<div class="col-11 menu-box h-full">
<div class="sub-box">
<div class="col-12 row-top col-start mb-5">
<div class="text-title text-blue">General</div>
</div>
<div class="row col-12">
<div class="col-12 p-2">
<table>
<ng-container *ngFor="let item of generalPages; let i = index">
<tbody class="table-link" [attr.data-disable-hover]="false" style="line-height: 2.25rem;">
<!-- <td class="text-menu-list row-top w-auto">
<a [routerLink]="null">
{{i + 1}}&nbsp;
</a>
</td> -->
<td class="text-menu-list">
<a class="li-text-menu-general table-link-link bullet" [routerLink]="null">
{{ item.text }}
</a>
</td>
</tbody>
</ng-container>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row col-6 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
Career Path
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'เส้นทางสายอาชีพของพนักงาน เพื่อให้พนักงานองค์กรได้เห็นโอกาสความก้าวหน้าในชีวิตการทำงาน',
'สามารถปรับระดับตามเส้นทางสายอาชีพของพนักงานได้',
'สามารถติดตามการโยกย้ายของพนักงานได้',
'เชื่อมโยงกับโครงสร้างเงินเดือน',
'เชื่อมโยงกับผลประเมิน Performance & Potential',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Career Path
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu2 bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 16rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 1rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu-general {
font-weight: 400;
font-size: 1.5rem;
line-height: normal;
}
.li-text-menu {
font-weight: 400;
font-size: 1.25rem;
line-height: normal;
}
.li-text-menu2 {
font-weight: 400;
font-size: 1rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-career-path',
templateUrl: './career-path.component.html',
styleUrls: ['./career-path.component.scss']
})
export class CareerPathComponent {
generalPages = [
{ text: "สรุปข้อมูลตำแหน่งงานว่าง", description: "" },
{ text: "สรุป JD ตำแหน่งงานว่าง", description: "" },
{ text: "สรุปข้อมูลพนักงานที่มีความประสงค์ขอโยกย้าย", description: "" },
{ text: "สรุปความเห็นผู้บังคับบัญชา หรือผู้ที่ต้องการรับโอนย้าย", description: "" },
];
menuList = [
[{ text: "ผังโครงสร้างองค์กร", description: "" },
{ text: "Job Family", description: "" },
{ text: "Job Grade", description: "" }],
[{ text: "Job Grade", description: "" },
{ text: "ข้อมูลตำแหน่งงาน", description: "" },
{ text: "เกณฑ์กติกา(Criteria) ในการ Promotion", description: "" }],
[{ text: "อายุตัว อายุงานในระดับ", description: "" },
{ text: "Job Classification", description: "" },
{ text: "ข้อมูลประวัติการ Promotion", description: "" }],
[{ text: "ข้อมูลการโยกย้าย", description: "" },
{ text: "อำนาจในการปรับ", description: "" }]
]
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Compensation Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture7.jpg" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Compensation</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
ระบบบริหารค่าตอบแทน
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'เปรียบเทียบในลักษณะ Basic Salary และ Remuneration',
'เทียบกับตลาดแรงงาน และถูกต้องตามกฎหมายแรงงาน',
'ผลสำรวจค่าตอบแทนเป็น Factor ที่สำคัญ',
'ผลประเมินค่างานทำให้งานน่าเชื่อถือ',
'โครงสร้างค่าตอบแทน มีอายุการใช้งาน 3-5 ปี',
'เชื่อมโยงกับ Career Path เสมอ',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Compensation
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 12rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu {
font-weight: 400;
font-size: 1.25rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-compensation',
templateUrl: './compensation.component.html',
styleUrls: ['./compensation.component.scss']
})
export class CompensationComponent {
menuList = [
[{ text: "โครงสร้างเงินเดือนขององค์กร", description: "" },
{ text: "Job Grade", description: "" },
{ text: "ผลประเมินค่างาน", description: "" },],
[{ text: "Starting Salary", description: "" },
{ text: "Placement พนักงานเทียบกับตลาด", description: "" },
{ text: "Job Description", description: "" },],
[{ text: "Job Classification", description: "" },
{ text: "Criteria", description: "" },
{ text: "การปรับเงินในกรณีต่างๆ เลื่อนตำแหน่ง", description: "" },],
[{ text: "Package Remuneration แต่ละตำแหน่งงาน", description: "" },
{ text: "เงินช่วยเหลือ", description: "" },
{ text: "เงินประจำตำแหน่ง", description: "" },],
[{ text: "ผลสำรวจค่าตอบแทนปัจจุบัน", description: "" },
{ text: "เปรียบเทียบเงินเดือนกับผลสำรวจ", description: "" },],
];
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
......@@ -65,8 +65,19 @@ import { JobFamilyMappingComponent } from '../job-family-mapping/job-family-mapp
import { JobFamilyMatrixComponent } from '../job-family-matrix/job-family-matrix.component';
import { DocumentUploadManagerComponent } from '../company-components/account-settings/document-upload-manager/document-upload-manager.component';
import { DisciplinaryActionComponent } from '../disciplinary-action/disciplinary-action.component';
import { OutstandingPerformanceComponent } from '../outstanding-performance/outstanding-performance.component';
import { OutstandingPerformanceComponent } from '../outstanding-performance/outstanding-performance.component';
import { PostEvaluationTrackingComponent } from '../post-evaluation-tracking/post-evaluation-tracking.component';
import { OnboardingProgramComponent } from '../onboarding-program/onboarding-program.component';
import { TalentSuccessorComponent } from '../talent-successor/talent-successor.component';
import { CareerPathComponent } from '../career-path/career-path.component';
import { TrainingrRoadmapComponent } from '../training-roadmap/training-roadmap.component';
import { LeadershipDevelopmentComponent } from '../leadership-development/leadership-development.component';
import { WorkforceComponent } from '../workforce/workforce.component';
import { CompensationComponent } from '../compensation/compensation.component';
import { SalarySurveyComponent } from '../salary-survey/salary-survey.component';
import { RecruitmentSelectionComponent } from '../recruitment-selection/recruitment-selection.component';
import { JobManagementComponent } from '../job-management/job-management.component';
import { WelfareRewardComponent } from '../welfare-reward/welfare-reward.component';
......@@ -148,7 +159,18 @@ const routes: Routes = [
{ path: "ess/job-family-matrix", title: 'รายละเอียดกลุ่มงานตามวิชาชีพ', component: JobFamilyMatrixComponent },
{ path: "ess/disciplinary-action", title: 'วินัยและการลงโทษ', component: DisciplinaryActionComponent },
{ path: "ess/outstanding-performance", title: 'ผลงานดีเด่น', component: OutstandingPerformanceComponent },
{ path: "ess/post-evaluation-tracking", title: 'ผลงานดีเด่น', component: PostEvaluationTrackingComponent },
{ path: "ess/post-evaluation-tracking", title: 'ติดตามหลังการประเมิน', component: PostEvaluationTrackingComponent },
{ path: "ess/onboarding-program", title: 'Onboarding Program', component: OnboardingProgramComponent },
{ path: "ess/talent-successor", title: 'Talent & Successor', component: TalentSuccessorComponent },
{ path: "ess/career-Path", title: 'Career Path', component: CareerPathComponent },
{ path: "ess/training-roadmap", title: 'Training Roadmap', component: TrainingrRoadmapComponent },
{ path: "ess/leadership-development", title: 'Leadership', component: LeadershipDevelopmentComponent },
{ path: "ess/workforce", title: 'Workforce', component: WorkforceComponent },
{ path: "ess/compensation", title: 'Compensation', component: CompensationComponent },
{ path: "ess/salary-survey", title: 'Salary Survey', component: SalarySurveyComponent },
{ path: "ess/recruitment-selection", title: 'Recruitment & Selection', component: RecruitmentSelectionComponent },
{ path: "ess/job-management", title: 'Job Management', component: JobManagementComponent },
{ path: "ess/welfare-reward", title: 'Welfare & Reward', component: WelfareRewardComponent },
]
}
];
......
......@@ -221,6 +221,19 @@ import { DisciplinaryActionComponent } from '../disciplinary-action/disciplinary
import { OutstandingPerformanceComponent } from '../outstanding-performance/outstanding-performance.component';
import { PostEvaluationTrackingComponent } from '../post-evaluation-tracking/post-evaluation-tracking.component';
import { EvaluationConfirmationComponent } from '../post-evaluation-tracking/evaluation-confirmation/evaluation-confirmation.component';
import { GapTrackingComponent } from '../post-evaluation-tracking/gap-tracking/gap-tracking.component';
import { GapTrackingSupervisorComponent } from '../post-evaluation-tracking/gap-tracking-supervisor/gap-tracking-supervisor.component';
import { OnboardingProgramComponent } from '../onboarding-program/onboarding-program.component';
import { TalentSuccessorComponent } from '../talent-successor/talent-successor.component';
import { CareerPathComponent } from '../career-path/career-path.component';
import { TrainingrRoadmapComponent } from '../training-roadmap/training-roadmap.component';
import { LeadershipDevelopmentComponent } from '../leadership-development/leadership-development.component';
import { WorkforceComponent } from '../workforce/workforce.component';
import { CompensationComponent } from '../compensation/compensation.component';
import { SalarySurveyComponent } from '../salary-survey/salary-survey.component';
import { RecruitmentSelectionComponent } from '../recruitment-selection/recruitment-selection.component';
import { JobManagementComponent } from '../job-management/job-management.component';
import { WelfareRewardComponent } from '../welfare-reward/welfare-reward.component';
export const MY_DATE_FORMATS = {
parse: {
......@@ -381,7 +394,20 @@ export class CustomDateAdapter extends NativeDateAdapter {
DisciplinaryActionComponent,
OutstandingPerformanceComponent,
PostEvaluationTrackingComponent,
EvaluationConfirmationComponent
EvaluationConfirmationComponent,
GapTrackingComponent,
GapTrackingSupervisorComponent,
OnboardingProgramComponent,
TalentSuccessorComponent,
CareerPathComponent,
TrainingrRoadmapComponent,
LeadershipDevelopmentComponent,
WorkforceComponent,
CompensationComponent,
SalarySurveyComponent,
RecruitmentSelectionComponent,
JobManagementComponent,
WelfareRewardComponent,
], imports: [
TranslateModule,
CommonModule,
......
......@@ -92,13 +92,13 @@
</div>
<div class="row">
<div class="col-3 ">
<div class="row row-top h-full">
<div class="row row-top ">
<div class="col-12 row-center col-center">
<img src="./assets/img/brand-logos/new_logo_mySkillX.png" alt="mySkillX" class="w-auto"
style="height: 8rem;" />
</div>
<div class="col-12 row-top col-center mt-5 h-full">
<div class="row col-11 row-center col-center dashboard-box" style="height: calc(100% - 9.25rem);">
<div class="row col-11 row-center col-center dashboard-box" style="height: 64vh;">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/HRD/1.png" alt="Performance illustration" class="hero-img" />
......@@ -137,12 +137,12 @@
<tbody class="table-link" [attr.data-disable-hover]="!documentManager.dataList.length"
[attr.data-hs-overlay]="documentManager.dataList.length ? '#download-file-manage-modal' : null"
style="line-height: 2.25rem;">
<td class="text-menu row-top w-auto">
<td class="text-menu-list row-top w-auto">
<a [routerLink]="item.link?item.link:null">
{{i + 1}}&nbsp;
</a>
</td>
<td class="text-menu">
<td class="text-menu-list">
<a class="table-link-link" [routerLink]="item.link?item.link:null">
{{ item.text }}
</a>
......@@ -150,13 +150,13 @@
</tbody>
</ng-container>
<ng-container *ngIf="item.text != 'Download เอกสาร'">
<tbody class="table-link" [attr.data-disable-hover]="!item.link" style="line-height: 2.25rem;">
<td class="text-menu row-top w-auto">
<tbody class="table-link" [attr.data-disable-hover]="false" style="line-height: 2.25rem;">
<td class="text-menu-list row-top w-auto">
<a [routerLink]="item.link?item.link:null">
{{i + 1}}&nbsp;
</a>
</td>
<td class="text-menu">
<td class="text-menu-list">
<a class="table-link-link" [routerLink]="item.link?item.link:null">
{{ item.text }}
</a>
......@@ -181,7 +181,7 @@
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 p-2 ">
<a [routerLink]="item.link?item.link:null" class="row sub-box-menu p-2 row-center"
[attr.data-disable-hover]="!item.link" style="min-height: 65px;">
[attr.data-disable-hover]="false" style="min-height: 65px;">
<div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
......@@ -208,7 +208,7 @@
<ng-container *ngFor="let item of items; let l = index">
<div class=" col-4 p-2 ">
<a [routerLink]=" item.link?item.link:null" class="row sub-box-menu p-2 row-center"
[attr.data-disable-hover]="!item.link" style="min-height: 65px;">
[attr.data-disable-hover]="false" style="min-height: 65px;">
<div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
......
......@@ -349,10 +349,18 @@ transition: transform $dur $easing,
transition: color .25s;
}
.text-menu-list {
font-weight: 400;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a {
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
......
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Job Management Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture11.png" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Job Management</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
Job Management
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'คำอธิบายวัตถุประสงค์หลักของหน่วยงาน',
'คำอธิบายหน้าที่หลักของแต่ละตำแหน่งงาน',
'คำอธิบายคุณสมบัติหลักของตำแหน่งงาน',
'คำอธิบายหน้าที่ที่นำมาอ้างอิง',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Job Management
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 12rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu {
font-weight: 400;
font-size: 1.5rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-job-management',
templateUrl: './job-management.component.html',
styleUrls: ['./job-management.component.scss']
})
export class JobManagementComponent {
menuList = [
[{ text: "Function Description", description: "" },
{ text: "Job Description", description: "" },
{ text: "Benchmark Job Description", description: "" },],
[{ text: "Job Specification ของแต่ละตำแหน่งงาน", description: "" },],
];
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">
Leadership Development Wizard
</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture5.png" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Leadership Development</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
Leadership Development
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'การพัฒนาผู้บริหาร หัวหน้างานทุกระดับ ให้มีทักษะทั้งการบังคับบัญชา ดูแลคน และการบริหารจัดการ ควบคู่กันไป',
'หลักสูตรเชื่อมโยงกับ Career Path',
'เกณฑ์กติกาที่เหมาะสมก่อนเข้าเรียน และหลังเรียน',
'หลักสูตรที่ Update ทันสมัยตรงตาม Business Plan หรือกลยุทธ์',
'ผู้จับหลักสูตรมาแล้วเป็นผู้นำที่พร้อมจะเป็นอนาคตให้กับองค์กร',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Leadership Development
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 25rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu {
font-weight: 400;
font-size: 1.25rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-leadership-development',
templateUrl: './leadership-development.component.html',
styleUrls: ['./leadership-development.component.scss']
})
export class LeadershipDevelopmentComponent {
menuList = [
[{ text: "Managerial Competency", description: "" },
{ text: "หลักสูตรมาตรฐาน", description: "" },
{ text: "รายชื่อผู้ที่มีเข้าแต่ละหลักสูตรมาตรฐาน", description: "" }],
[{ text: "เกณฑ์ และปัจจัยของผู้มีสิทธิ์เข้าหลักสูตร", description: "" },
{ text: "Course Outline", description: "" },
{ text: "ข้อมูล E-learning", description: "" }],
[{ text: "ข้อมูลประวัติฝึกอบรม", description: "" },
{ text: "Project Assignment", description: "" },
{ text: "การติดตามผล", description: "" }],
];
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
......@@ -31,8 +31,7 @@
<ng-container *ngFor="let sliceNum of [[0,3],[3,6]];let i=index">
<div class="flex flex-row" style="gap:1.2rem">
<ng-container *ngFor="let m of hrdModules | slice:sliceNum[0] : sliceNum[1] ;let f = first">
<div class="flex-1 module-card" [routerLink]=" f ? '/ess/employee-self-service' :null"
(click)="!f ? goToWebsite('https://www.myhr.co.th/') : null">
<div class="flex-1 module-card" (click)="goTo(m.link)">
<img [src]="m.icon" [alt]="m.title + ' icon'" class="module-img" />
<p class="module-label">
<span class="font-semibold text-sky-600">One X</span><br />
......@@ -57,7 +56,7 @@
<ng-container *ngFor="let sliceNum of [[0,3],[3,6]];let i=index">
<div class="flex flex-row" style="gap:1.2rem">
<ng-container *ngFor="let m of hrmModules | slice:sliceNum[0] : sliceNum[1] ;let f = first">
<div class="flex-1 module-card" (click)="goToWebsite('https://www.myhr.co.th/')">
<div class="flex-1 module-card" (click)="goTo(m.link)">
<img [src]="m.icon" [alt]="m.title + ' icon'" class="module-img" />
<p class="module-label">
<span class="font-semibold text-sky-600">One X</span><br />
......@@ -74,7 +73,7 @@
</section>
<!-- eco-system pill --------------------------------------------------->
<!-- <div (click)="goToWebsite('https://www.myhr.co.th/')"
<!-- <div (click)="goTo('https://www.myhr.co.th/')"
class="eco-pill bp-glow mx-auto mt-5 text-center !p-0 cursor-pointer">
<span class="flex flex-row" style="font-size: 30px;align-items: center;justify-content: center;">
Eco system <span class="font-semibold">myHR</span>
......@@ -115,8 +114,7 @@
<div class="bp-grid">
<ng-container *ngFor="let m of hrdModules let f = first">
<div class="module-card" [routerLink]=" f ? '/ess/employee-self-service' :null"
(click)="!f ? goToWebsite('https://www.myhr.co.th/') : null">
<div class="module-card" (click)="goTo(m.link)">
<img [src]="m.icon" [alt]="m.title + ' icon'" class="module-img" />
<p class="module-label">
<span class="font-semibold text-sky-600">One X</span><br />
......@@ -137,7 +135,7 @@
<div class="bp-grid">
<ng-container *ngFor="let m of hrmModules">
<div class="module-card" (click)="goToWebsite('https://www.myhr.co.th/')">
<div class="module-card" (click)="goTo(m.link)">
<img [src]="m.icon" [alt]="m.title + ' icon'" class="module-img" />
<p class="module-label">
<span class="font-semibold text-sky-600">One X</span><br />
......@@ -152,7 +150,7 @@
</section>
<!-- eco-system pill --------------------------------------------------->
<!-- <div (click)="goToWebsite('https://www.myhr.co.th/')"
<!-- <div (click)="goTo('https://www.myhr.co.th/')"
class="eco-pill bp-glow mx-auto mt-5 text-center !p-0 cursor-pointer">
<span class="flex flex-row" style="font-size: 30px;align-items: center;justify-content: center;">
Eco system <span class="font-semibold">myHR</span>
......
import { Component, EventEmitter, Input, Output } from '@angular/core';
type ModuleCard = { icon: string; title: string };
import { Router } from '@angular/router';
type ModuleCard = { link: string, icon: string; title: string };
@Component({
selector: 'app-my-skill-x-module',
templateUrl: './my-skill-x-module.component.html',
......@@ -7,24 +8,30 @@ type ModuleCard = { icon: string; title: string };
})
export class MySkillXModuleComponent {
hrdModules: ModuleCard[] = [
{ icon: 'assets/img/logos/HRD/1.png', title: 'Performance & Competency' },
{ icon: 'assets/img/logos/HRD/2.png', title: 'On-Boarding Program' },
{ icon: 'assets/img/logos/HRD/3.png', title: 'Talent & Successor' },
{ icon: 'assets/img/logos/HRD/4.png', title: 'Career Path' },
{ icon: 'assets/img/logos/HRD/5.png', title: 'Training Roadmap' },
{ icon: 'assets/img/logos/HRD/6.png', title: 'Leadership' }
{ link: '/ess/employee-self-service', icon: 'assets/img/logos/HRD/1.png', title: 'Performance & Competency' },
{ link: '/ess/onboarding-program', icon: 'assets/img/logos/HRD/2.png', title: 'On-Boarding Program' },
{ link: '/ess/talent-successor', icon: 'assets/img/logos/HRD/3.png', title: 'Talent & Successor' },
{ link: '/ess/career-Path', icon: 'assets/img/logos/HRD/4.png', title: 'Career Path' },
{ link: '/ess/training-roadmap', icon: 'assets/img/logos/HRD/5.png', title: 'Training Roadmap' },
{ link: '/ess/leadership-development', icon: 'assets/img/logos/HRD/6.png', title: 'Leadership' }
];
hrmModules: ModuleCard[] = [
{ icon: 'assets/img/logos/HDM/1.png', title: 'Workforce' },
{ icon: 'assets/img/logos/HDM/2.png', title: 'Compensation' },
{ icon: 'assets/img/logos/HDM/3.png', title: 'Salary Survey' },
{ icon: 'assets/img/logos/HDM/4.png', title: 'Recruit & Selection' },
{ icon: 'assets/img/logos/HDM/5.png', title: 'JD & Org Chart' },
{ icon: 'assets/img/logos/HDM/6.png', title: 'Welfare & Reward' }
{ link: '/ess/workforce', icon: 'assets/img/logos/HDM/1.png', title: 'Workforce' },
{ link: '/ess/compensation', icon: 'assets/img/logos/HDM/2.png', title: 'Compensation' },
{ link: '/ess/salary-survey', icon: 'assets/img/logos/HDM/3.png', title: 'Salary Survey' },
{ link: '/ess/recruitment-selection', icon: 'assets/img/logos/HDM/4.png', title: 'Recruit & Selection' },
{ link: '/ess/job-management', icon: 'assets/img/logos/HDM/5.png', title: 'Job Management' },
{ link: '/ess/welfare-reward', icon: 'assets/img/logos/HDM/6.png', title: 'Welfare & Reward' }
];
constructor(private router: Router) { }
goToWebsite(web: string) {
window.open(web, '_blank');
goTo(link?: string) {
if (link) {
this.router.navigate([link]);
} else {
window.open('https://www.myhr.co.th/', '_blank');
}
}
}
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Onboarding Program Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture1.png" alt="Performance illustration" class="hero-img"
style="margin-right: 26px;" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Onboarding Program</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
Onboarding Program
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of ['ระบบพี่เลี้ยงที่ช่วยรักษาคนในช่วงเข้ามาใหม่ให้อยู่กับองค์กร',
'การเข้าใจ Culture และการปรับตัวของพนักงานใหม่',
'แผนการเรียนงานสำหรับพนักงานใหม่',
'การประเมินเพื่อปรับตัว และสามารถทำงานได้',
'คู่มือสำหรับพี่เลี้ยง']; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Onboarding Program
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 25rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu {
font-weight: 400;
font-size: 1.5rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-onboarding-program',
templateUrl: './onboarding-program.component.html',
styleUrls: ['./onboarding-program.component.scss']
})
export class OnboardingProgramComponent {
menuList = [
[{ text: "ข้อมูลพนักงานใหม่", description: "" },
{ text: "ข้อมูลพี่เลี้ยง", description: "" },
{ text: "ข้อมูลปฐมนิเทศ", description: "" }],
[{ text: "แผนการเรียนงาน", description: "" },
{ text: "ผลประเมินพนักงานใหม่", description: "" },
{ text: "ประวัติการเรียนงาน", description: "" }],
[{ text: "คู่มือสำหรับพี่เลี้ยง", description: "" }]
];
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
......@@ -297,8 +297,18 @@
<div class="flex !items-center"
*ngFor="let competencyCourse of data.competencyCourse"
style="min-height: 100px;flex-direction:column">
<i class="ti ti-book fs-xxl !fw-b"></i><br>
{{competencyCourse.competencyCourseId }}
<div class="row">
<div class="col-6"><i class="ti ti-book fs-xxl !fw-b"></i></div>
<div class="col-6" style="align-content: center;">
{{competencyCourse.competencyCourseId }}
</div>
<div class="col-12">
<img [src]="'./assets/img/logos/myLearn_Gray.png'">
</div>
<!-- <div class="col-12">
<img [src]="'./assets/img/logos/logo_myLearn.jpg'">
</div> -->
</div>
</div>
</ng-container>
</td>
......
......@@ -67,3 +67,22 @@ table, .card, .section-block {
// break-after: auto !important;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
......@@ -79,7 +79,11 @@
</ng-template>
<ng-template #template let-data>
<i class="ti ti-eye cursor-pointer i-gray fs-l px-1" (click)="page=2"></i>
<i class="ti ti-file cursor-pointer i-gray fs-l px-1" (click)="openEmployeeDialog()"></i>
<div class="relative" style="display: inline-block;">
<i class="ti ti-file cursor-pointer i-gray fs-l px-1" (click)="openEmployeeDialog()"></i>
<span class="absolute"
style="top: 0; right: 5px; width: 8px; height: 8px; background-color: red; border-radius: 50%; border: 1px solid white; "></span>
</div>
</ng-template>
</e-column>
</e-columns>
......
......@@ -86,6 +86,9 @@ export class EvaluationConfirmationComponent {
@ViewChild('employeeDialog') employeeDialog: any
employeeDialogRef: any
evaluaterId = ''
@ViewChild('pdfArea') pdfArea!: ElementRef<HTMLElement>;
constructor(private appraisalService: AppraisalService,
private fileService: FileService,
private translateService: TranslateService,
......@@ -248,7 +251,6 @@ export class EvaluationConfirmationComponent {
}
}
@ViewChild('pdfArea') pdfArea!: ElementRef<HTMLElement>;
async exportPdf() {
const el = this.pdfArea?.nativeElement;
......
<div class="flex item-center w-full font-size-18px font-weight-700 text-primary px-5 mt-1 mb-4"
style="height: 50px;align-items: center;border-width: 1px;background: #eff6fe; border-radius:20px">
{{'SubordinateList' | translate}}
</div>
<div class="flex w-full mb-4">
<div class="flex w-1/4 justify-between">
<div class="flex">
<div class="flex items-center">
<input type="checkbox" class="ti-form-checkbox pointer-events-none" id="hs-default-checkbox"
[checked]="selectEmp.size-1 > 0">
<label for="hs-default-checkbox" class="text-sm text-gray-500 mx-2 pointer-events-none">
{{selectEmp.size-1 < 0 ? 0 : selectEmp.size-1}} {{'Selected' | translate}} </label>
</div>
<div class="mx-1 flex items-center">
<button (click)="toggleSelectAll()" class="focus:ring-2 focus:ring-primary rounded-sm flex item-center">
<i class="fs-l transition-all duration-200"
[ngClass]="{'ri-checkbox-multiple-line text-gray-500': !selectEmp.get('selectAll'), 'ri-checkbox-multiple-fill text-primary': selectEmp.get('selectAll')}"></i>
</button>
<label (click)="toggleSelectAll()" class="text-sm text-gray-500 ml-2 cursor-pointer">
{{'SelectAll' |translate}}</label>
</div>
</div>
</div>
<div class="flex w-3/4 justify-end">
<div class="px-1">
<button type="button" class="ti-btn ti-btn-soft-secondary h-45px m-0 shadow-md"
[class.ti-btn-disabled]="selectEmp.size-1 <= 0" [disabled]="selectEmp.size-1 <= 0"
(click)="approveAll()">
{{'ApproveAll' | translate}}
</button>
</div>
<div class="px-1">
<div class="relative shadow-md">
<input type="text" class="ti-form-input ltr:pl-11 rtl:pr-11 focus:z-10 "
[placeholder]="'SearchByNoOrName' | translate" [(ngModel)]="search" (ngModelChange)="setSyncfutionDataList()">
<div
class="absolute inset-y-0 ltr:left-0 rtl:right-0 flex items-center pointer-events-none z-20 ltr:pl-4 rtl:pr-4">
<i class="ri-search-line text-gray"></i>
</div>
</div>
</div>
</div>
</div>
<div class="flex flex-col w-100">
<div class="mb-4">
<ng-container *ngTemplateOutlet="Datagrid"></ng-container>
</div>
</div>
<ng-template #Datagrid>
<ejs-grid #grid id='Grid' [locale]="locale" [dataSource]="syncfution.dataList" [allowFiltering]="true"
[filterSettings]="filterSettings" [selectionSettings]="selectionOptions"
[searchSettings]="syncfution.searchSettings" [groupSettings]="groupSettings" [toolbar]="toolbarOptions"
[editSettings]="editSettings" [loadingIndicator]='loadingIndicator' [query]="query"
[columnMenuItems]="columnMenuItems" [pageSettings]="initialPage" [allowMultiSorting]="true" [allowPaging]="true"
[allowGrouping]="true" [allowSorting]="true" [showColumnMenu]="true" [allowPdfExport]="true"
[allowExcelExport]="true" [allowReordering]="true" width="auto" rowHeight="60" allowEditing="false"
(columnMenuClick)="onColumnMenuClick($event)" (toolbarClick)='toolbarClick($event)'>
<e-columns>
<ng-container *ngFor="let col of syncfution.columns">
<ng-container *ngIf="col.headerText">
<e-column [field]="col.field" [headerText]="col.headerText" [width]="col.width" [format]="col.format"
[isPrimaryKey]="col.isPrimaryKey" [validationRules]="col.validationRules" [visible]="col.visible"
[editType]="false" [allowEditing]="false" [allowFiltering]="true" [allowSorting]="true" [type]="col.type"
textAlign="center">
<ng-template #headerTemplate let-data>
<span class="font-size-12px font-weight-700 text-primary">
{{ col.headerText | translate}}
</span>
</ng-template>
<ng-template #template let-data *ngIf="col.headerText=='EmployeeCode'">
<div class="flex-col gap-2">
<input type="checkbox" class="ti-form-checkbox cursor-pointer"
[checked]="selectEmp.get(data.employeeId)"
(click)="!selectEmp.get(data.employeeId)?selectEmp.set(data.employeeId , true):selectEmp.delete(data.employeeId);checkSelectAll()">
&nbsp;
<img class=" avatar shadow-none rounded-full !ring-transparent object-cover h-12 w-12"
[src]="data.picture?getImg(data.picture):'./assets/img/users/defaultperson.jpg'"
(error)="onImageError($event)">
{{data.employeeId}}
</div>
</ng-template>
</e-column>
</ng-container>
</ng-container>
<e-column headerText='action' textAlign='Center'>
<ng-template #headerTemplate let-data>
<span class="font-size-12px font-weight-700 text-primary">{{'Action' | translate}}</span>
</ng-template>
<ng-template #template let-data>
<i class="ti ti-edit cursor-pointer i-gray fs-l px-1" (click)="openGapDialog()"></i>
</ng-template>
</e-column>
</e-columns>
<e-aggregates>
<e-aggregate>
<e-columns>
<e-column *ngFor="let col of aggregatesSum" [field]="col.field" [type]="'Sum'"
[footerTemplate]="'Sum: ${Sum}'" [groupFooterTemplate]="'Sum: ${Sum}'"
[groupCaptionTemplate]="col.groupCaptionTemplate" [format]="col.format">
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column *ngFor="let col of aggregatesCount" [field]="col.field" [type]="'Count'"
[footerTemplate]="'Count: ${Count}'" [groupFooterTemplate]="'Count: ${Count}'"
[groupCaptionTemplate]="col.groupCaptionTemplate" [format]="col.format">
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column *ngFor="let col of aggregatesAvg" [field]="col.field" [type]="'Average'"
[footerTemplate]="'Average: ${Average}'" [groupFooterTemplate]="'Average: ${Average}'"
[groupCaptionTemplate]="col.groupCaptionTemplate" [format]="col.format">
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column *ngFor="let col of aggregatesMin" [field]="col.field" [type]="'Min'"
[footerTemplate]="'Min: ${Min}'" [groupFooterTemplate]="'Min: ${Min}'"
[groupCaptionTemplate]="col.groupCaptionTemplate" [format]="col.format">
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column *ngFor="let col of aggregatesMax" [field]="col.field" [type]="'Max'"
[footerTemplate]="'Max: ${Max}'" [groupFooterTemplate]="'Max: ${Max}'"
[groupCaptionTemplate]="col.groupCaptionTemplate" [format]="col.format">
</e-column>
</e-columns>
</e-aggregate>
</e-aggregates>
</ejs-grid>
</ng-template>
<ng-template #gapDialog let-modal>
<h3 mat-dialog-title>
<!-- {{'รายงานสรุปผลการประเมิน' | translate}} -->
<div class="relative">
<div class="absolute" style="top: -43px;">
{{'ดำเนินการปิด Gap' | translate}}
</div>
<div class="absolute" style="right: 0;top: -43px;">
<button type="button" class="hs-dropdown-toggle ti-modal-clode-btn text-danger" mat-button [mat-dialog-close]>
<span class="sr-only">Close</span>
<i class="ti ti-circle-x fs-xxl"></i>
</button>
</div>
</div>
</h3>
<mat-dialog-content>
<app-gap-tracking></app-gap-tracking>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button type="button" mat-button [mat-dialog-close]
class="hs-dropdown-toggle ti-btn ti-border font-medium bg-white text-gray-700 shadow-sm align-middle hover:bg-gray-50 focus:ring-offset-white focus:ring-primary dark:bg-bgdark dark:hover:bg-black/20 dark:border-white/10 dark:text-white/70 dark:hover:text-white dark:focus:ring-offset-white/10">
ย้อนกลับ
</button>
<button type="button" (click)="save()" class="ti-btn ti-btn-success">
{{'SaveData' | translate}}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
// th{
// position: relative; // เทียบเท่า class "relative"
// padding: 10px; // เทียบเท่า class "px-10px py-10px" (อาจเปลี่ยนตามต้องการ)
// background-color: rgb(96 165 250 / 0.1); // ตัวอย่างแทน "bg-soft-secondary"
// color: #2b2b2b; // ตัวอย่างแทน "text-primary"
// text-align: center !important; // เทียบเท่า "!text-center"
// // หากต้องการดีไซน์อื่น ๆ เพิ่มเติมก็ใส่ในนี้ได้เลย เช่น:
// font-weight: 600;
// border-bottom: 1px solid #eee;
// }
.e-headercell,
.e-detailheadercell {
background-color: rgb(96 165 250 / 0.1) !important;
}
.e-pager .e-currentitem,
.e-pager .e-currentitem:hover {
background: rgb(96 165 250) !important;
color: #fff;
opacity: 1 !important;
}
.e-checkbox-wrapper .e-frame.e-check,
.e-css.e-checkbox-wrapper .e-frame.e-check {
background-color: rgb(96 165 250) !important;
border-color: transparent;
color: #fff;
}
.e-checkbox-wrapper .e-frame,
.e-css.e-checkbox-wrapper .e-frame {
border: 1px solid !important;
border-radius: 2px;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-family: "e-icons";
height: 18px;
line-height: 10px;
padding: 2px 0;
text-align: center;
vertical-align: middle;
width: 1rem !important;
border-color: #64748b !important;
}
.e-grid td.e-selectionbackground {
background-color: #aec2ec !important;
}
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-3-9 {
flex: 0 0 32.5%;
max-width: 32.5%;
}
@for $i from 1 through 100 {
.m-#{$i}rem {
margin: #{$i}rem;
}
.mt-#{$i}rem {
margin-top: #{$i}rem;
}
.ml-#{$i}rem {
margin-left: #{$i}rem;
}
.mb-#{$i}rem {
margin-bottom: #{$i}rem;
}
.mr-#{$i}rem {
margin-right: #{$i}rem;
}
.p-#{$i}rem {
padding: #{$i}rem;
}
.pt-#{$i}rem {
padding-top: #{$i}rem;
}
.pl-#{$i}rem {
padding-left: #{$i}rem;
}
.pb-#{$i}rem {
padding-bottom: #{$i}rem;
}
.pr-#{$i}rem {
padding-right: #{$i}rem;
}
}
@media print {
body * {
visibility: hidden;
/* ซ่อนทุก element */
}
#printArea,
#printArea * {
visibility: visible;
/* แสดงเฉพาะ #printArea */
}
#printArea {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
}
.pdf-container {
transform: translateZ(0
);
}
.mx-0 {
margin-left: 0 !important;
margin-right: 0 !important;
}
\ No newline at end of file
// th{
// position: relative; // เทียบเท่า class "relative"
// padding: 10px; // เทียบเท่า class "px-10px py-10px" (อาจเปลี่ยนตามต้องการ)
// background-color: rgb(96 165 250 / 0.1); // ตัวอย่างแทน "bg-soft-secondary"
// color: #2b2b2b; // ตัวอย่างแทน "text-primary"
// text-align: center !important; // เทียบเท่า "!text-center"
// // หากต้องการดีไซน์อื่น ๆ เพิ่มเติมก็ใส่ในนี้ได้เลย เช่น:
// font-weight: 600;
// border-bottom: 1px solid #eee;
// }
.e-headercell,
.e-detailheadercell {
background-color: rgb(96 165 250 / 0.1) !important;
}
.e-pager .e-currentitem,
.e-pager .e-currentitem:hover {
background: rgb(96 165 250) !important;
color: #fff;
opacity: 1 !important;
}
.e-checkbox-wrapper .e-frame.e-check,
.e-css.e-checkbox-wrapper .e-frame.e-check {
background-color: rgb(96 165 250) !important;
border-color: transparent;
color: #fff;
}
.e-checkbox-wrapper .e-frame,
.e-css.e-checkbox-wrapper .e-frame {
border: 1px solid !important;
border-radius: 2px;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-family: "e-icons";
height: 18px;
line-height: 10px;
padding: 2px 0;
text-align: center;
vertical-align: middle;
width: 1rem !important;
border-color: #64748b !important;
}
.e-grid td.e-selectionbackground {
background-color: #aec2ec !important;
}
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-3-9 {
flex: 0 0 32.5%;
max-width: 32.5%;
}
@for $i from 1 through 100 {
.m-#{$i}rem {
margin: #{$i}rem;
}
.mt-#{$i}rem {
margin-top: #{$i}rem;
}
.ml-#{$i}rem {
margin-left: #{$i}rem;
}
.mb-#{$i}rem {
margin-bottom: #{$i}rem;
}
.mr-#{$i}rem {
margin-right: #{$i}rem;
}
.p-#{$i}rem {
padding: #{$i}rem;
}
.pt-#{$i}rem {
padding-top: #{$i}rem;
}
.pl-#{$i}rem {
padding-left: #{$i}rem;
}
.pb-#{$i}rem {
padding-bottom: #{$i}rem;
}
.pr-#{$i}rem {
padding-right: #{$i}rem;
}
}
@media print {
body * {
visibility: hidden;
/* ซ่อนทุก element */
}
#printArea,
#printArea * {
visibility: visible;
/* แสดงเฉพาะ #printArea */
}
#printArea {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
}
.pdf-container {
transform: translateZ(0
);
}
.mx-0 {
margin-left: 0 !important;
margin-right: 0 !important;
}
\ No newline at end of file
......@@ -19,12 +19,12 @@
<a style="border-radius: 20px;width: 210px;height: 35px;"
class="border justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900"
href="javascript:void(0);" id="card-type-item-2" data-hs-tab="#card-type-2" aria-controls="card-type-2">
{{'การติดตามผล Gap' | translate}}
{{'Follow Gap' | translate}}
</a>
<a style="border-radius: 20px;width: 210px;height: 35px;"
class="border justify-center rounded-4px hs-tab-active:!bg-primary hs-tab-active:border-primary hs-tab-active:!text-white -mb-px py-2 px-3 inline-flex items-center gap-2 font-size-16px font-weight-500 text-center text-gray-600 hover:text-gray-900"
href="javascript:void(0);" id="card-type-item-3" data-hs-tab="#card-type-3" aria-controls="card-type-3">
{{'ติดตามผล Gap โดยหัวหน้า' | translate}}
{{'Supervisor Follow Gap' | translate}}
</a>
</nav>
<div class="pt-20px">
......@@ -32,10 +32,10 @@
<app-evaluation-confirmation></app-evaluation-confirmation>
</div>
<div id="card-type-2" class="hidden" role="tabpanel" aria-labelledby="card-type-item-2">
<app-evaluation-confirmation></app-evaluation-confirmation>
<app-gap-tracking></app-gap-tracking>
</div>
<div id="card-type-3" class="hidden" role="tabpanel" aria-labelledby="card-type-item-3">
<app-evaluation-confirmation></app-evaluation-confirmation>
<app-gap-tracking-supervisor></app-gap-tracking-supervisor>
</div>
</div>
</div>
......
......@@ -20,11 +20,4 @@ import { setCulture } from '@syncfusion/ej2-base';
styleUrls: ['./post-evaluation-tracking.component.scss']
})
export class PostEvaluationTrackingComponent {
@Output() sendPathTitle: EventEmitter<string[]> = new EventEmitter<string[]>();
currentTab = 1
onSendPathTitle(pathTitle: string) {
this.sendPathTitle.emit(['menu.Organization', 'menu.Company', 'BusinessUnit', pathTitle])
}
}
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Recruitment & Selection Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture10.png" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Recruitment & Selection</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
ระบบสรรหา และคัดเลือก
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'การสรรหาให้ทันเวลา และความต้องการ',
'เทคนิคการคัดเลือกคน',
'เครื่องมือในการคัดเลือกคน',
'การเห็น Candidate เข้ามาทำงานตามใบ Request',
'การลดเวลาสรรหา โดยเฉพาะตำแหน่งสำคัญ',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Recruitment & Selection
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
/* ===== base variables ===== */
$size-card : 150px; // ( ≥1280px จะขยายเป็น 170 )
$col-hero : 280px; // ความกว้างคอลัมน์ซ้าย
$gap-main : 2.5rem;
$radius-main : 28px;
$radius-sub : 20px;
$dur : .35s;
$easing : cubic-bezier(.4, 0, .2, 1);
$shadow-base : 0 14px 30px -12px rgba(0, 0, 0, .18);
$shadow-deep : 0 20px 42px -16px rgba(0, 0, 0, .24);
/* ===== wrapper ===== */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 3rem 1.25rem;
margin-top: 5rem;
}
/* ===== GRID ชั้นแรก ===== */
.page-grid {
display: grid;
gap: $gap-main;
grid-template-columns: $col-hero 1fr;
@media (max-width: 1023px) {
/* < lg : 1 คอลัมน์ */
grid-template-columns: 1fr;
}
}
/* ===== HERO CARD (คงเดิม – ตัด flex ออก) ===== */
.hero-card {
width: 100%;
max-width: 280px; // ไม่เกินจอ desktop
box-sizing: border-box;
padding-inline: clamp(1rem, 4vw, 1.75rem);
padding-block: 2rem 3rem;
position: relative;
border-radius: $radius-main;
padding: 2rem 1.75rem 3rem;
background: #fff;
box-shadow: $shadow-base;
text-align: center;
display: grid;
place-items: center;
gap: 1.3rem;
transition: transform $dur $easing, box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
/* glow */
&.bp-glow::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
}
&:hover.bp-glow::before {
opacity: .27;
}
}
@media (max-width: 639px) {
.hero-img {
max-width: 68%;
}
}
.hero-img {
width: 17rem;
}
.hero-label {
font: 600 .95rem/1.2 'Inter', sans-serif;
color: #3b82f6;
}
.hero-title {
font: 700 1.5rem/1.3 'Inter', sans-serif;
color: #1e3a8a;
}
.hero-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-full px-10 py-2 transition;
}
.back-link {
position: absolute;
left: 1.75rem;
bottom: 1rem;
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
/* ===== GRID ชั้นสอง – เมนูย่อย 2 แถวพอดี ===== */
.sub-grid {
display: grid;
grid-auto-flow: column;
/* เติมแนวนอนก่อน */
grid-template-rows: repeat(2, $size-card);
grid-auto-columns: $size-card;
gap: 1.5rem;
place-content: start;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
/* ≥1280px ขยายการ์ด */
@media (min-width: 1280px) {
grid-template-rows: repeat(2, 170px);
grid-auto-columns: 170px;
}
/* มือถือ: 2 คอลัมน์เสมอ */
@media (max-width: 639px) {
grid-template-rows: repeat(2, 46vw);
grid-auto-columns: 46vw;
}
}
/* ===== SUB-CARD + เอฟเฟกต์ ===== */
.sub-card {
// aspect-ratio: 1 / 1;
position: relative;
border-radius: $radius-sub;
background: rgba(255, 255, 255, .5);
/* glass */
backdrop-filter: blur(9px) saturate(170%);
box-shadow: 0 8px 18px -10px rgba(71, 85, 105, .25);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
cursor: pointer;
user-select: none;
transition: transform .45s $easing, box-shadow .45s $easing, background .45s;
/* gradient rim */
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
// background: linear-gradient(160deg,#60a5fa,#818cf8 50%,#a855f7);
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: .45;
transition: opacity .4s;
}
&:hover {
background: #ffffff;
transform: translateY(-7px) rotateX(5deg) rotateY(-3deg);
box-shadow: $shadow-deep;
&::before {
opacity: .9;
}
}
}
.sub-title {
font-weight: 600;
font-size: .9rem;
line-height: 1.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
.sub-title2 {
font-weight: 600;
font-size: 1.5rem;
line-height: 2.25rem;
color: #2563eb;
pointer-events: none;
word-break: break-word;
}
// div {
// border: black 1px solid;
// min-height: 20px;
// }
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 1;
}
@for $i from 1 through 12 {
$width: (
$i / 12) * 100%;
.col-#{$i} {
flex: 0 0 $width;
max-width: $width;
}
}
.col-start {
display: flex;
justify-content: start;
}
.col-center {
display: flex;
justify-content: center;
}
.row-top {
display: flex;
align-items: start;
align-content: start;
}
.row-center {
display: flex;
align-items: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.dashboard-link {
font-size: .9rem;
color: #64748b;
transition: color .25s;
&:hover {
color: #3b82f6;
}
}
.dashboard-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2
);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.menu-box {
box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
background-origin: border-box;
background-clip: content-box,
border-box;
transition: transform $dur $easing,
box-shadow $dur $easing;
&:hover {
transform: translateY(-6px);
box-shadow: $shadow-deep;
}
&:hover::before {
content: '';
position: absolute;
inset: -3px;
border-radius: inherit;
// background: linear-gradient(135deg, #4f46e5, #ec4899 60%, #f59e0b);
filter: blur(34px);
opacity: .17;
z-index: -1;
transition: opacity $dur;
opacity: .27;
border: 1px solid;
}
.sub-box {
padding: 2rem;
}
}
.text-blue {
color: #3b82f6;
}
.text-title-head {
font-weight: 600;
font-size: 2.5rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-title {
font-weight: 600;
font-size: 2rem;
line-height: 2.25rem;
pointer-events: none;
word-break: break-word;
}
.text-menu {
font-weight: 500;
font-size: 1rem;
transition: color .25s;
}
.text-menu-list {
font-weight: 300;
line-height: 58px;
font-size: 2rem;
transition: color 0.25s;
}
.table-link {
transition: color 0.25s;
&[data-disable-hover="false"]:hover .text-menu a,
&[data-disable-hover="false"]:hover .li-text-menu,
&[data-disable-hover="false"]:hover .text-menu-list a {
color: #3b82f6;
cursor: pointer;
&.table-link-link {
text-decoration: underline;
}
}
&[data-disable-hover="true"] {
opacity: 0.5;
cursor: default;
}
}
.sub-box-menu {
border: #3b82f6 1px solid;
border-radius: 15px;
min-height: 50px;
&:hover {
cursor: pointer;
background: rgba(59, 130, 246, 0.2);
}
&[data-disable-hover="true"] {
--tw-bg-opacity: 1;
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
&:hover {
background-color: rgb(226 232 240 / var(--tw-bg-opacity));
cursor: default;
}
}
}
.text-no {
font-weight: 600;
font-size: 1.5rem;
}
.back-button {
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid rgb(37 99 235);
cursor: pointer;
display: inline-block;
transition: transform 0.2s;
}
.back-button:hover {
border-right: 30px solid rgb(29 78 216);
}
ul {
list-style-type: disc;
/* disc, circle, square, none */
}
.li-text-menu {
font-weight: 400;
font-size: 1.25rem;
line-height: normal;
}
.bullet {
display: list-item;
list-style-type: disc;
margin-left: 20px;
}
\ No newline at end of file
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { DocumentManagerModel, MyDocumentManagerModel } from 'src/app/shared/model/document-manager.model';
import { DocumentManagerService } from 'src/app/shared/services/documents.service';
import { FileService } from 'src/app/shared/services/file.service';
import Swal from 'sweetalert2';
interface SubModule {
title: SafeHtml;
route?: string;
file?: string;
}
@Component({
selector: 'app-recruitment-selection',
templateUrl: './recruitment-selection.component.html',
styleUrls: ['./recruitment-selection.component.scss']
})
export class RecruitmentSelectionComponent {
menuList = [
[{ text: "ตำแหน่งงานว่าง", description: "" },
{ text: "JD ของตำแหน่งงานว่าง", description: "" },
{ text: "Job Specification ของตำแหน่งงานว่าง", description: "" },],
[{ text: "การเปรียบเทียบคู่ Candidate (Persona)", description: "" },
{ text: "ข้อสอบสรรหา", description: "" },
{ text: "ฐานข้อมูลของผู้สมัคร", description: "" },],
[{ text: "ตรวจสอบประวัติของ Candidate", description: "" },
{ text: "การแจ้งผล", description: "" },
{ text: "ส่งต่อฐานข้อมูล", description: "" },],
];
documentManager: { loading: boolean, dataList: DocumentManagerModel[] } = { loading: false, dataList: [] }
constructor(private sanitizer: DomSanitizer,
private fileService: FileService,
private cdr: ChangeDetectorRef,
private translateService: TranslateService,
private documentManagerService: DocumentManagerService
) {
}
ngOnInit(): void {
this.getDocumentManagerList()
}
getDocumentManagerList() {
this.documentManager.loading = true
this.documentManagerService.getList().subscribe({
next: response => {
this.documentManager.dataList = response.map(x => {
return new MyDocumentManagerModel(x)
})
this.documentManager.loading = false
this.cdr.detectChanges();
}, error: error => {
this.documentManager.loading = false
console.error('Error fetching employee types:', error);
this.cdr.detectChanges()
}
})
}
openReport(file: string) {
const url = 'assets/reports/' + file;
window.open(url, '_blank');
}
downloadFile(fileName: string) {
this.fileService.downloadFiles(fileName).subscribe({
next: response => {
const url = window.URL.createObjectURL(response);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.cdr.detectChanges()
}, error: error => {
this.showAlert(error.message, 'error')
this.cdr.detectChanges()
}
})
}
showAlert(text: string, type: 'success' | 'error') {
Swal.fire({
icon: type,
title: 'แจ้งเตือน',
text: text,
showCancelButton: false,
confirmButtonText: 'ยืนยัน',
})
}
translateText(th?: string, en?: string) {
return this.translateService.getCurrentLang() == 'th' ? (th || '') : (en || '')
}
}
<div class="relative m-2">
<div class="row absolute w-full">
<div class="col-12">
<div class="row-center col-center relative row">
<div class="col-12" style="justify-content: start;display: flex;">
<a class="back-button absolute col-12" routerLink="/ess/my-skill-x-module">
</a>
</div>
<div class="text-title-head text-blue">Salary Survey Wizard</div>
</div>
</div>
</div>
<div class="row ">
<div class="row col-3" style="margin-top: 4rem">
<div class="row col-11 row-center col-center dashboard-box">
<div class="row col-12 sub-box h-full">
<div class="col-12 row-center col-center m-2">
<img src="assets/img/logos/wizard/Picture9.png" alt="Performance illustration" class="hero-img" />
</div>
<div class="col-12 row-center col-center m-2">
<h4 class="hero-label hero-title text-blue">One X</h4>
</div>
<div class="col-12 row-center col-center m-2">
<h3 class="hero-title text-blue">Salary Survey</h3>
</div>
<div class="col-12 row-center col-center m-2">
<button routerLink="/dashboard/projects" class="hero-btn" style="height: 80px;">Dashboard</button>
</div>
<!-- <div class="col-12 row-center col-start m-2">
<a routerLink="/ess/my-skill-x-module" class="dashboard-link">
<i class="ti ti-arrow-left"></i> กลับสู่เมนูหลัก
</a>
</div> -->
</div>
</div>
</div>
<div class="row col-9 row-top" style="margin-top: 4rem;">
<div class="row col-12 row-top col-center menu-box">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
การสำรวจค่าตอบแทน
</div>
</div>
<div class="row col-12">
<ul class="col-12" style="padding-left: 2rem;">
<ng-container *ngFor="let items of [
'ช่วยให้รู้กลยุทธ์การจ่ายค่าจ้างและให้สวัสดิการของตลาด แล้วนำมาปรับใช้ในองค์กรได้',
'ช่วยให้รู้สภาวะของคู่แข่งขันในกลุ่มธุรกิจเดียวกัน',
'ช่วยกำหนดจุดยืนของการจ่ายค่าตอบแทนให้กับพนักงานได้ว่าควรจะจ่ายอย่างไร จ่ายเท่าไหร่ จึงจะจูงใจให้ มีคนสมัครงาน และสามารถรักษาพนักงานไม่ให้หลุดไปอยู่กับคู่แข่งได้',
'มีข้อมูลที่ช่วยให้ผู้บริหารสามารถกำหนดงบประมาณในเรื่องต่าง ๆ ได้ชัดเจนมากขึ้นในด้านต้นทุนการ ผลิต การพัฒนาพนักงาน และการให้ commission แก่พนักงานขายเพื่อจูงใจในการขายสินค้า เป็นต้น',
]; let i = index">
<li class="table-link " [attr.data-disable-hover]="false">
<div class="li-text-menu table-link-link">
{{items}}
</div>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
<div class="row col-12 row-top col-center menu-box mt-5">
<div class="sub-box col-12">
<div class="col-12 mb-5">
<div class="text-title text-blue">
One X Salary Survey
</div>
</div>
<div class="row col-12">
<ng-container *ngFor="let items of menuList; let i = index">
<ng-container *ngFor="let item of items; let l = index">
<div class="col-4 row py-2">
<div class="col-11">
<a [routerLink]="null" class="row sub-box-menu p-3 row-center " [attr.data-disable-hover]="false"
style="min-height: 65px;">
<!-- <div class="col-2">
<span
class="flex align-items-center justify-content-center rounded-circle text-white bg-primary text-left text-no">
{{(i*3)+l+1}}
</span>
</div> -->
<div class="col text-menu li-text-menu bullet">
{{item.text}}
</div>
</a>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment