- ปรับรูปแบบ template html
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<!-- <span class="bg-red-100 text-red-800 p-2 rounded-lg text-xl">💸</span> -->
|
||||
<span>จัดสรรงบประมาณ</span>
|
||||
</h2>
|
||||
<p class="text-gray-500 mt-1 ml-1 text-sm">โครงการ: <span class="font-medium text-red-900">{{projectTitle}}</span></p>
|
||||
<p class="text-gray-500 mt-1 ml-1 text-sm">โครงการ: <span class="font-medium text-red-900">{{projectTitle || prjnam}}</span></p>
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 bg-white px-4 py-2 rounded-full shadow-sm border border-gray-100">
|
||||
รายการทั้งหมด: <span class="font-bold text-red-800">{{ myTrnMst.length }}</span> รายการ
|
||||
@@ -26,7 +26,7 @@
|
||||
<!-- <span class="bg-red-600 text-white w-6 h-6 flex items-center justify-center rounded-full text-xs shadow-sm">
|
||||
{{ isEditMode ? '✎' : '✚' }}
|
||||
</span> -->
|
||||
{{ isEditMode ? 'แก้ไขรายการ' : 'เพิ่มรายการงบประมาณ' }}
|
||||
<span class="w-1 h-6 bg-red-900 rounded-full mr-1"></span>{{ isEditMode ? 'แก้ไขรายการ' : 'เพิ่มรายการงบประมาณ' }}
|
||||
</div>
|
||||
<button class="text-gray-400 transition-transform duration-300" [ngClass]="{'rotate-180': isFormExpanded}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ToastrService } from 'ngx-toastr';
|
||||
})
|
||||
export class BudgetAproval implements OnInit {
|
||||
@Output() ExpenseEventSubmit = new EventEmitter<any>();
|
||||
@Input() prjnam!: string;
|
||||
|
||||
budgetForm!: FormGroup;
|
||||
isFormExpanded = true;
|
||||
|
||||
@@ -1,126 +1,124 @@
|
||||
<div class="w-full p-6">
|
||||
|
||||
<div class="w-full p-6">
|
||||
|
||||
<!-- Summary Cards -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-6 mb-8">
|
||||
<!--
|
||||
<div class="bg-white border border-gray-200 rounded-2xl p-5 shadow-sm hover:shadow-md transition">
|
||||
<div class="text-gray-500 text-sm">งบทั้งหมด</div>
|
||||
<div class="text-3xl font-bold text-gray-800 mt-1">
|
||||
{{ totalBudget | number:'1.0-2' }} บาท
|
||||
<div class="flex flex-col md:flex-row justify-between items-end mb-6 gap-4">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
|
||||
<span class="w-2 h-8 bg-red-900 rounded-full"></span> รายการโครงการทั้งหมด
|
||||
</h1>
|
||||
<p class="text-gray-500 mt-1 text-sm pl-4">จัดการงบประมาณและตรวจสอบสถานะโครงการ</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white border border-gray-200 rounded-2xl p-5 shadow-sm hover:shadow-md transition">
|
||||
<div class="text-gray-500 text-sm">งบที่อนุมัติแล้ว</div>
|
||||
<div class="text-3xl font-bold text-green-600 mt-1">
|
||||
{{ approvedBudget | number:'1.0-2' }} บาท
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden">
|
||||
|
||||
<div class="bg-white border border-gray-200 rounded-2xl p-5 shadow-sm hover:shadow-md transition">
|
||||
<div class="text-gray-500 text-sm">งบคงเหลือ</div>
|
||||
<div
|
||||
class="text-3xl font-bold mt-1"
|
||||
[ngClass]="remainingBudget >= 0 ? 'text-blue-600' : 'text-red-600'"
|
||||
>
|
||||
{{ remainingBudget | number:'1.0-2' }} บาท
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Add Button -->
|
||||
<!-- <div class="mb-4">
|
||||
<button
|
||||
class=" rounded-3xl bg-green-600 hover:bg-green-700 text-white px-5 py-2.5 text-sm font-medium shadow-sm flex items-center gap-2 transition"
|
||||
>
|
||||
➕ เพิ่มโครงการใหม่
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Table -->
|
||||
<div class="overflow-x-auto bg-white border border-gray-200 rounded-2xl shadow-sm">
|
||||
<table class="min-w-full text-left border-collapse">
|
||||
<thead class="bg-red-900 border-b border-gray-200 text-white text-sm">
|
||||
<tr>
|
||||
<th class="py-3 px-4 font-semibold">ลำดับ</th>
|
||||
<th class="py-3 px-4 font-semibold">รหัสโครงการ</th>
|
||||
<th class="py-3 px-4 font-semibold">ชื่อโครงการ</th>
|
||||
<th class="py-3 px-4 font-semibold">ผู้รับผิดชอบ</th>
|
||||
<th class="py-3 px-4 font-semibold">งบที่ขออนุมัติ</th>
|
||||
<th class="py-3 px-4 font-semibold">หมวดงบ</th>
|
||||
<th class="py-3 px-4 font-semibold">จำนวนที่อนุมัติ</th>
|
||||
<th class="py-3 px-4 font-semibold text-center">สถานะ</th>
|
||||
<th class="py-3 px-4 font-semibold text-center">ดำเนินการ</th>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr class="bg-red-900 text-white text-sm uppercase tracking-wider leading-normal">
|
||||
<th class="py-4 px-6 font-medium w-16 text-center">ลำดับ</th>
|
||||
<th class="py-4 px-6 font-medium min-w-[200px]">ชื่อโครงการ / รหัส</th>
|
||||
<th class="py-4 px-6 font-medium">ผู้รับผิดชอบ</th>
|
||||
<th class="py-4 px-6 font-medium text-right">งบที่ขอ (บาท)</th>
|
||||
<th class="py-4 px-6 font-medium text-right">อนุมัติ (บาท)</th>
|
||||
<th class="py-4 px-6 font-medium text-center">สถานะ</th>
|
||||
<th class="py-4 px-6 font-medium text-center">จัดการ</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@for(idx of myPrjMst; track idx.prjseq; let i = $index){
|
||||
<tr class="border-b border-gray-100 hover:bg-blue-50/20 transition">
|
||||
<td class="py-4 px-4 text-gray-700">{{ i + 1 }}</td>
|
||||
<td class="py-4 px-4 font-medium text-gray-700"> {{ idx.prjseq }}</td>
|
||||
<td class="py-4 px-4 text-gray-800 font-semibold leading-tight">{{ idx.prjnam }}</td>
|
||||
<td class="py-4 px-4 text-gray-700">{{ idx.prjusrnam }}</td>
|
||||
<td class="py-4 px-4 text-blue-700 font-bold whitespace-nowrap"> {{ idx.prjwntbdg | number:'1.0-0' }} บาท</td>
|
||||
<tbody class="text-gray-600 text-sm">
|
||||
@for(idx of myPrjMst; track idx.prjseq; let i = $index) {
|
||||
<tr class="border-b border-gray-100 hover:bg-red-50/40 transition duration-200 group">
|
||||
|
||||
@if(idx.prjbdgnam){
|
||||
<td class="py-4 px-4 text-gray-800 font-semibold leading-tight">{{ idx.prjbdgnam }}</td>
|
||||
}@else {
|
||||
<td class="py-4 px-4 text-gray-400 font-semibold leading-tight italic">ไม่จัดสรร</td>
|
||||
}
|
||||
|
||||
<td class="py-4 px-4 w-40">
|
||||
<!-- <input type="number" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl bg-white focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-300 text-sm transition"/> -->
|
||||
{{ idx.prjacpbdg }} บาท
|
||||
<td class="py-4 px-6 text-center text-gray-400 font-mono">
|
||||
{{ i + 1 }}
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-4 text-center">
|
||||
<span
|
||||
class="px-3 py-1.5 rounded-full text-xs font-semibold inline-flex items-center gap-1
|
||||
shadow-sm border"
|
||||
<td class="py-4 px-6">
|
||||
<div class="flex flex-col">
|
||||
<span class="font-bold text-gray-800 text-base group-hover:text-red-900 transition-colors">
|
||||
{{ idx.prjnam }}
|
||||
</span>
|
||||
<span class="text-xs text-gray-400 mt-1 font-mono bg-gray-100 inline-block px-1.5 py-0.5 rounded w-fit">
|
||||
#{{ idx.prjseq }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center text-gray-500 text-xs font-bold">
|
||||
{{ idx.prjusrnam?.charAt(0) }}
|
||||
</div>
|
||||
<span class="font-medium">{{ idx.prjusrnam }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-6 text-right">
|
||||
<span class="font-mono text-gray-600">
|
||||
{{ idx.prjwntbdg | number:'1.0-0' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-6 text-right">
|
||||
<span class="font-mono font-bold text-lg"
|
||||
[ngClass]="{
|
||||
'text-green-600': (idx.prjacpbdg ?? 0) > 0,
|
||||
'text-gray-300': !idx.prjacpbdg || idx.prjacpbdg === 0
|
||||
}">
|
||||
{{ (idx.prjacpbdg ?? 0) | number:'1.0-0' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-6 text-center">
|
||||
<span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-semibold border"
|
||||
[ngClass]="{
|
||||
'bg-yellow-50 text-yellow-700 border-yellow-200': idx.prjcomstt === 'UAC',
|
||||
'bg-green-50 text-green-700 border-green-200': idx.prjcomstt === 'BAP',
|
||||
'bg-red-50 text-red-700 border-red-200': idx.prjcomstt === 'CN'
|
||||
}"
|
||||
>
|
||||
<ng-container *ngIf="idx.prjcomstt === 'BAP'">อนุมัติแล้ว</ng-container>
|
||||
<ng-container *ngIf="idx.prjcomstt === 'UAC'">รออนุมัติ</ng-container>
|
||||
<ng-container *ngIf="idx.prjcomstt === 'CN'">ไม่อนุมัติ</ng-container>
|
||||
}">
|
||||
<span class="w-1.5 h-1.5 rounded-full"
|
||||
[ngClass]="{
|
||||
'bg-yellow-500': idx.prjcomstt === 'UAC',
|
||||
'bg-green-500': idx.prjcomstt === 'BAP',
|
||||
'bg-red-500': idx.prjcomstt === 'CN'
|
||||
}"></span>
|
||||
|
||||
@if(idx.prjcomstt === 'UAC'){ รออนุมัติ }
|
||||
@else if(idx.prjcomstt === 'BAP'){ อนุมัติแล้ว }
|
||||
@else if(idx.prjcomstt === 'CN'){ ไม่อนุมัติ }
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="py-4 px-4 text-center space-x-2 whitespace-nowrap">
|
||||
|
||||
<button
|
||||
class="bg-red-900 hover:bg-red-950 text-white px-4 py-2 rounded-xl text-sm
|
||||
shadow-sm font-medium transition"
|
||||
(click)="openBudgetDetail(idx)">
|
||||
จัดสรรงบประมาณ
|
||||
<td class="py-4 px-6 text-center">
|
||||
<button (click)="openBudgetDetail(idx)"
|
||||
class="text-red-900 hover:text-white border border-red-900 hover:bg-red-900 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-xs px-4 py-2 text-center transition-all duration-200 shadow-sm flex items-center justify-center gap-1 mx-auto whitespace-nowrap">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
จัดสรรงบ
|
||||
</button>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
} @empty {
|
||||
<tr>
|
||||
<td colspan="7" class="py-12 text-center text-gray-400">
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<svg class="w-12 h-12 text-gray-300 mb-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
||||
</svg>
|
||||
<span>ไม่พบข้อมูลโครงการในระบบ</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- endtable -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Pagination
|
||||
<div class="flex justify-end items-center gap-3 mt-5">
|
||||
<button class="px-4 py-2 border border-gray-300 rounded-xl bg-white hover:bg-gray-100">
|
||||
1
|
||||
</button>
|
||||
<button class="px-4 py-2 border border-gray-300 rounded-xl bg-white hover:bg-gray-100">
|
||||
2
|
||||
</button>
|
||||
</div> -->
|
||||
<div class="bg-gray-50 px-6 py-4 border-t border-gray-200 flex justify-between items-center text-xs text-gray-500">
|
||||
<div>แสดง {{ myPrjMst.length }} รายการ</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,12 @@ export class MainManagerComponent implements OnInit {
|
||||
}
|
||||
|
||||
openBudgetDetail(idx: IPrjMst) {
|
||||
this.router.navigate(['/main/budget/approve', idx.prjseq]);
|
||||
this.router.navigate(['/main/manager/aproval'], {
|
||||
state: {
|
||||
prjseq: idx.prjseq,
|
||||
prjnam: idx.prjnam
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<span>เพิ่มโครงการ</span>
|
||||
</button>
|
||||
|
||||
<!-- โครงการ -->
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm border-collapse">
|
||||
<thead class="bg-red-900 text-white">
|
||||
@@ -25,6 +26,8 @@
|
||||
<th class="py-3 px-4 text-center rounded-tr-lg w-20">ดำเนินการ</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<!-- เนื้อหา -->
|
||||
<tbody>
|
||||
<tr class="border-b hover:bg-gray-50 transition duration-100">
|
||||
<td class="py-3 px-4 text-gray-700">1</td>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<app-budget-aproval (ExpenseEventSubmit)="OnBudgetExp($event)"></app-budget-aproval>
|
||||
<app-budget-aproval (ExpenseEventSubmit)="OnBudgetExp($event)" [prjnam]="prjNam"></app-budget-aproval>
|
||||
|
||||
@@ -14,16 +14,24 @@ export class BudgetAprovalContent implements OnInit {
|
||||
|
||||
myTrnmst: ITrnmst[]=[];
|
||||
myDropBdg: IDropBdg[]=[];
|
||||
constructor(
|
||||
prjSeq:string = '';
|
||||
prjNam:string = '';
|
||||
; constructor(
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private generalService: GeneralService,
|
||||
private transactionStateService: TransactionStateService
|
||||
){}
|
||||
){
|
||||
const nav = this.router.getCurrentNavigation();
|
||||
if (nav?.extras.state) {
|
||||
this.prjSeq = nav.extras.state['prjseq'];
|
||||
this.prjNam = nav.extras.state['prjnam'];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
let param = this.route.snapshot.paramMap.get('seq');
|
||||
this.OnSearchTrn(param);
|
||||
// this.prjSeq = this.route.snapshot.param.get('seq');
|
||||
this.OnSearchTrn(this.prjSeq);
|
||||
this.OnBudgetSearch();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ export class MainManagerContentComponent implements OnInit {
|
||||
private generalService: GeneralService,
|
||||
private projectStateService: ProjectStateService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.OnSearchPrj({}, true);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ const routes: Routes = [
|
||||
{ path: 'manager', component: MainManagerContentComponent },
|
||||
{ path: 'project', component: MainProjectContent },
|
||||
{ path: 'project/:mode', component: MainProjectContent },
|
||||
{ path: 'budget/approve/:seq', component: BudgetAprovalContent},
|
||||
// {
|
||||
// path: 'manager',
|
||||
// children: [
|
||||
// { path: '', component: MainManagerContentComponent }, // รายการโครงการ
|
||||
// { path: 'budget/:code', component: BudgetAproval }, // จัดการงบประมาณ
|
||||
// ]
|
||||
// },
|
||||
// { path: 'budget/approve/:seq', component: BudgetAprovalContent},
|
||||
{
|
||||
path: 'manager',
|
||||
children: [
|
||||
{ path: '', component: MainManagerContentComponent }, // รายการโครงการ
|
||||
{ path: 'aproval', component: BudgetAprovalContent }, // จัดการงบประมาณ
|
||||
]
|
||||
},
|
||||
// children: [
|
||||
// {
|
||||
// path: 'dashboard',
|
||||
|
||||
@@ -5,7 +5,7 @@ export interface IPrjMst {
|
||||
prjwntbdg?: string;
|
||||
prjbdgnam?: string;
|
||||
prjbdgcod?: string;
|
||||
prjacpbdg?: string;
|
||||
prjacpbdg?: number;
|
||||
prjcomstt?: string;
|
||||
prjacpdtm?: string;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,23 @@ export class TransactionStateService {
|
||||
this.transactionState.next(transactions);
|
||||
}
|
||||
|
||||
// 🟢 [NEW] อัปเดตหรือเพิ่มรายการเดียว
|
||||
setStateEditOne(item: ITrnmst): void {
|
||||
const current = this.transactionState.getValue() || [];
|
||||
|
||||
// หา index จาก trnseq (หรือ key อื่นที่ unique)
|
||||
const index = current.findIndex(x => x.trnseq === item.trnseq);
|
||||
|
||||
if (index !== -1) {
|
||||
// กรณีมีอยู่แล้ว -> อัปเดตข้อมูลทับ
|
||||
current[index] = { ...current[index], ...item };
|
||||
this.transactionState.next([...current]); // spread เพื่อ trigger change detection
|
||||
} else {
|
||||
// กรณีไม่มี (รายการใหม่) -> เพิ่มต่อท้าย
|
||||
this.transactionState.next([...current, item]);
|
||||
}
|
||||
}
|
||||
|
||||
// เคลียร์ state
|
||||
clearState(): void {
|
||||
this.transactionState.next(null);
|
||||
|
||||
Reference in New Issue
Block a user