diff --git a/ng-ttc-frontend/package-lock.json b/ng-ttc-frontend/package-lock.json index 0961f76..bbd14cb 100644 --- a/ng-ttc-frontend/package-lock.json +++ b/ng-ttc-frontend/package-lock.json @@ -25,15 +25,14 @@ "@fortawesome/free-brands-svg-icons": "^7.1.0", "@fortawesome/free-regular-svg-icons": "^7.1.0", "@fortawesome/free-solid-svg-icons": "^7.1.0", - "@tailwindcss/postcss": "^4.1.16", + "@tailwindcss/postcss": "^4.1.17", "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "dotenv": "^17.2.3", "jwt-decode": "^4.0.0", "ng2-charts": "^6.0.1", - "postcss": "^8.5.6", "rxjs": "~7.8.0", - "tailwindcss": "^4.1.16", + "tailwindcss": "^4.1.17", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, @@ -54,7 +53,7 @@ "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", "ngx-toastr": "^19.1.0", - "postcss": "^8.5.3", + "postcss": "^8.5.6", "typescript": "~5.9.3" } }, @@ -8275,7 +8274,6 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -12051,7 +12049,6 @@ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -13816,7 +13813,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -19904,7 +19900,6 @@ "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", @@ -20911,6 +20906,7 @@ "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", diff --git a/ng-ttc-frontend/package.json b/ng-ttc-frontend/package.json index c52bb52..2f00fd2 100644 --- a/ng-ttc-frontend/package.json +++ b/ng-ttc-frontend/package.json @@ -57,15 +57,14 @@ "@fortawesome/free-brands-svg-icons": "^7.1.0", "@fortawesome/free-regular-svg-icons": "^7.1.0", "@fortawesome/free-solid-svg-icons": "^7.1.0", - "@tailwindcss/postcss": "^4.1.16", + "@tailwindcss/postcss": "^4.1.17", "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "dotenv": "^17.2.3", "jwt-decode": "^4.0.0", "ng2-charts": "^6.0.1", - "postcss": "^8.5.6", "rxjs": "~7.8.0", - "tailwindcss": "^4.1.16", + "tailwindcss": "^4.1.17", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, @@ -86,7 +85,7 @@ "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", "ngx-toastr": "^19.1.0", - "postcss": "^8.5.3", + "postcss": "^8.5.6", "typescript": "~5.9.3" } } diff --git a/ng-ttc-frontend/public/ballot_0.png b/ng-ttc-frontend/public/ballot_0.png new file mode 100644 index 0000000..587321d Binary files /dev/null and b/ng-ttc-frontend/public/ballot_0.png differ diff --git a/ng-ttc-frontend/public/bell_0.png b/ng-ttc-frontend/public/bell_0.png new file mode 100644 index 0000000..9033761 Binary files /dev/null and b/ng-ttc-frontend/public/bell_0.png differ diff --git a/ng-ttc-frontend/public/calendar_0.png b/ng-ttc-frontend/public/calendar_0.png new file mode 100644 index 0000000..9e8486b Binary files /dev/null and b/ng-ttc-frontend/public/calendar_0.png differ diff --git a/ng-ttc-frontend/public/chart-histogram_0.png b/ng-ttc-frontend/public/chart-histogram_0.png new file mode 100644 index 0000000..e271693 Binary files /dev/null and b/ng-ttc-frontend/public/chart-histogram_0.png differ diff --git a/ng-ttc-frontend/public/chart-simple.png b/ng-ttc-frontend/public/chart-simple.png new file mode 100644 index 0000000..4f7bbc6 Binary files /dev/null and b/ng-ttc-frontend/public/chart-simple.png differ diff --git a/ng-ttc-frontend/public/check_0.png b/ng-ttc-frontend/public/check_0.png new file mode 100644 index 0000000..3e073fd Binary files /dev/null and b/ng-ttc-frontend/public/check_0.png differ diff --git a/ng-ttc-frontend/public/coins_0.png b/ng-ttc-frontend/public/coins_0.png new file mode 100644 index 0000000..8307ac9 Binary files /dev/null and b/ng-ttc-frontend/public/coins_0.png differ diff --git a/ng-ttc-frontend/public/exclamation_0.png b/ng-ttc-frontend/public/exclamation_0.png new file mode 100644 index 0000000..d5c4a6b Binary files /dev/null and b/ng-ttc-frontend/public/exclamation_0.png differ diff --git a/ng-ttc-frontend/public/exit_0.png b/ng-ttc-frontend/public/exit_0.png new file mode 100644 index 0000000..1e42767 Binary files /dev/null and b/ng-ttc-frontend/public/exit_0.png differ diff --git a/ng-ttc-frontend/public/form_0.png b/ng-ttc-frontend/public/form_0.png new file mode 100644 index 0000000..3bb344b Binary files /dev/null and b/ng-ttc-frontend/public/form_0.png differ diff --git a/ng-ttc-frontend/public/home (1)_0.png b/ng-ttc-frontend/public/home (1)_0.png new file mode 100644 index 0000000..4c1f9c7 Binary files /dev/null and b/ng-ttc-frontend/public/home (1)_0.png differ diff --git a/ng-ttc-frontend/public/home_0.png b/ng-ttc-frontend/public/home_0.png new file mode 100644 index 0000000..dbae118 Binary files /dev/null and b/ng-ttc-frontend/public/home_0.png differ diff --git a/ng-ttc-frontend/public/icons8-home-384.png b/ng-ttc-frontend/public/icons8-home-384.png new file mode 100644 index 0000000..cd4af1e Binary files /dev/null and b/ng-ttc-frontend/public/icons8-home-384.png differ diff --git a/ng-ttc-frontend/public/interrogation.png b/ng-ttc-frontend/public/interrogation.png new file mode 100644 index 0000000..dc91bca Binary files /dev/null and b/ng-ttc-frontend/public/interrogation.png differ diff --git a/ng-ttc-frontend/public/interrogation_0.png b/ng-ttc-frontend/public/interrogation_0.png new file mode 100644 index 0000000..f9a8926 Binary files /dev/null and b/ng-ttc-frontend/public/interrogation_0.png differ diff --git a/ng-ttc-frontend/public/locked-computer_0.png b/ng-ttc-frontend/public/locked-computer_0.png new file mode 100644 index 0000000..ec69243 Binary files /dev/null and b/ng-ttc-frontend/public/locked-computer_0.png differ diff --git a/ng-ttc-frontend/public/menu-burger_0.png b/ng-ttc-frontend/public/menu-burger_0.png new file mode 100644 index 0000000..18afa1c Binary files /dev/null and b/ng-ttc-frontend/public/menu-burger_0.png differ diff --git a/ng-ttc-frontend/public/pencil_0.png b/ng-ttc-frontend/public/pencil_0.png new file mode 100644 index 0000000..6d7cc83 Binary files /dev/null and b/ng-ttc-frontend/public/pencil_0.png differ diff --git a/ng-ttc-frontend/public/plus-small_0.png b/ng-ttc-frontend/public/plus-small_0.png new file mode 100644 index 0000000..524297a Binary files /dev/null and b/ng-ttc-frontend/public/plus-small_0.png differ diff --git a/ng-ttc-frontend/public/search_0.png b/ng-ttc-frontend/public/search_0.png new file mode 100644 index 0000000..3950982 Binary files /dev/null and b/ng-ttc-frontend/public/search_0.png differ diff --git a/ng-ttc-frontend/public/settings (1)_0.png b/ng-ttc-frontend/public/settings (1)_0.png new file mode 100644 index 0000000..7a85563 Binary files /dev/null and b/ng-ttc-frontend/public/settings (1)_0.png differ diff --git a/ng-ttc-frontend/public/stamp_0.png b/ng-ttc-frontend/public/stamp_0.png new file mode 100644 index 0000000..eff1d87 Binary files /dev/null and b/ng-ttc-frontend/public/stamp_0.png differ diff --git a/ng-ttc-frontend/public/user_0.png b/ng-ttc-frontend/public/user_0.png new file mode 100644 index 0000000..9afed7b Binary files /dev/null and b/ng-ttc-frontend/public/user_0.png differ diff --git a/ng-ttc-frontend/src/app/app-routing.module.ts b/ng-ttc-frontend/src/app/app-routing.module.ts index ee3b68c..533010d 100644 --- a/ng-ttc-frontend/src/app/app-routing.module.ts +++ b/ng-ttc-frontend/src/app/app-routing.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { SidebarContentComponent } from './content/sidebar-content/sidebar-content.component'; import { LicensePrivacyTermsComponent } from './component/license-privacy-terms/license-privacy-terms.component'; -// import { authGuard } from './services/auth.guard'; +import { authGuard } from './services/auth.guard'; const routes: Routes = [ @@ -14,7 +14,7 @@ const routes: Routes = [ path: 'main', component: SidebarContentComponent, canActivate: [ - // authGuard + authGuard ], children: [ { diff --git a/ng-ttc-frontend/src/app/app.module.ts b/ng-ttc-frontend/src/app/app.module.ts index dcffdd5..c2d33fd 100644 --- a/ng-ttc-frontend/src/app/app.module.ts +++ b/ng-ttc-frontend/src/app/app.module.ts @@ -23,6 +23,7 @@ import { LicensePrivacyTermsComponent } from './component/license-privacy-terms/ import { provideCharts, withDefaultRegisterables } from 'ng2-charts'; +// import { BudgetAproval } from './component/budget-aproval/budget-aproval'; // import { AccDateFormatPipe } from './pipe/dtmtodatetime.pipe'; // import { DtmtodatetimePipe } from './dtmtodatetime.pipe'; @@ -33,6 +34,7 @@ import { provideCharts, withDefaultRegisterables } from 'ng2-charts'; SidebarContentComponent, SidebarComponent, LicensePrivacyTermsComponent, + // BudgetAproval, // AccDateFormatPipe // DtmtodatetimePipe, // MainDashboardContentComponent, diff --git a/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.css b/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.css new file mode 100644 index 0000000..e69de29 diff --git a/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.html b/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.html new file mode 100644 index 0000000..279e184 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.html @@ -0,0 +1,197 @@ +
+ + +
+

+ รายการงบประมาณของโครงการ: {{ project?.name }} +

+ +
+ แสดงข้อมูล {{ budgetItems.length }} รายการ +
+
+ + + +
+ +

เพิ่มรายการงบประมาณ

+ +
+ + +
+ + + + +
+ กรุณาเลือกหมวดงบ +
+
+ + +
+ + +
+ กรุณาเลือกรายการ +
+
+ + +
+ + + +
+ จำนวนต้องมากกว่า 0 +
+
+ + +
+ + + +
+ ราคาต้องมากกว่า 0 +
+
+ +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับสถานะรหัสชื่อรายการจำนวนราคา/หน่วยยอดชำระดำเนินการ
{{ i + 1 }} + + {{ item.code }}{{ item.name }} + + + {{ item.price | number:'1.0-2' }} + + {{ item.qty * item.price | number:'1.0-2' }} + + + + +
+
+ + + +
+ ยอดรวมทั้งหมด: + + {{ getTotalAmount() | number:'1.0-2' }} บาท + +
+ +
diff --git a/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.ts b/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.ts new file mode 100644 index 0000000..07f7c9c --- /dev/null +++ b/ng-ttc-frontend/src/app/component/budget-aproval/budget-aproval.ts @@ -0,0 +1,109 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms'; +import { GeneralService } from '../../services/generalservice'; +import { IDropAct, IStateDrop, IStateResultResponse, IActData, IActSumData } from '../../interfaces/dashboard.interface' +import { DashboardStateService } from '../../services/state/dashboard-state.service'; +import { Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-budget-aproval', + standalone: false, + templateUrl: './budget-aproval.html', + styleUrl: './budget-aproval.css', +}) +export class BudgetAproval { + projectCode: any; + project: any; + addItemForm!: FormGroup; + + budgetItems = [ + { code: 'ITEM001', name: 'เอกซ์เรย์', qty: 1, price: 1000 }, + { code: 'ITEM002', name: 'กรอกคำสั่งซื้อ', qty: 1, price: 1500 }, + { code: 'ITEM003', name: 'ตรวจพื้นฐาน', qty: 1, price: 1000 }, + ]; + + budgetCategoriesDrop = { + expense: [ + { dtlcod: 'BDG001', dtlnam: 'เงินรายได้' }, + { dtlcod: 'BDG002', dtlnam: 'งบดำเนินงาน ปวส.' }, + { dtlcod: 'BDG003', dtlnam: 'โครงการส่งเสริมพัฒนาทักษะวิชาชีพทักษะพื้นฐาน' }, + { dtlcod: 'BDG004', dtlnam: 'ค่ากิจกรรมพัฒนาคุณภาพผู้เรียน' }, + { dtlcod: 'BDG005', dtlnam: 'อุดหนุนส่งเสริมและพัฒนาผู้เรียนองค์การวิชาชีพแห่งประเทศไทย (อวท.)' }, + { dtlcod: 'BDG006', dtlnam: 'งบดำเนินงาน ระยะสั้น' }, + { dtlcod: 'BDG007', dtlnam: 'โครงการบูรณาการการพัฒนาทักษะทางวิชาชีพกับการเสริมสร้างคุณลักษณะอันพึงประสงค์ (FIX IT)' }, + { dtlcod: 'BDG008', dtlnam: 'โครงการพัฒนาทักษะและสมรรถนะวิชาชีพกำลังคน (Up-skill, Re-skill)' }, + { dtlcod: 'BDG009', dtlnam: 'งบดำเนินงาน ปวช.' }, + { dtlcod: 'BDG010', dtlnam: 'โครงการขยายและยกระดับการจัดอาชีวศึกษาระบบทวิภาคีคุณภาพสูง' }, + { dtlcod: 'BDG011', dtlnam: 'ปวช.(สอจ)' }, + { dtlcod: 'BDG012', dtlnam: 'ค่าจัดการเรียนการสอน' }, + { dtlcod: 'BDG013', dtlnam: 'งบดำเนินงาน 170000' }, + { dtlcod: 'BDG014', dtlnam: 'โครงการพัฒนาทักษะและศักยภาพภาพการจัดการเรียนการสอนอาชีวศึกษา' }, + { dtlcod: 'BDG015', dtlnam: 'ศึกษาธิการ' }, + { dtlcod: 'BDG016', dtlnam: 'Up-skill' }, + { dtlcod: 'BDG017', dtlnam: 'ติดตามผู้สำเร็จ' }, + { dtlcod: 'BDG018', dtlnam: 'ทวิภาคี' }, + { dtlcod: 'BDG019', dtlnam: 'พันธุกรรม' }, + { dtlcod: 'BDG020', dtlnam: 'ปวส(สาธารณูประโภค)' }, + { dtlcod: 'BDG021', dtlnam: 'ปวส(ค่าสาธารณูปโภค)' }, + { dtlcod: 'BDG022', dtlnam: 'งบดำเนินงาน (ค่าสาธารณูปโภค)' }, + { dtlcod: 'BDG023', dtlnam: 'ค่าหนังสือเรียน' }, + { dtlcod: 'BDG024', dtlnam: 'โครงการอาชีวะต้านยาเสพติด' }, + { dtlcod: 'BDG025', dtlnam: 'ค่าตอบแทนพนักงานราชการ' }, + { dtlcod: 'BDG026', dtlnam: 'ค่าอุปกรณ์การเรียน' }, + { dtlcod: 'BDG027', dtlnam: 'โครงการยกระดับและพัฒนาขีดความสามารถด้านภาษาและทักษะดิจิทัลเพื่อพัฒนากำลังคนให้มีสมรรถนะสูง' }, + { dtlcod: 'BDG028', dtlnam: 'โครงการอนุรักษ์พันธุกรรมพืชอันเนื่องมาจากพระราชดำริ' }, + { dtlcod: 'BDG029', dtlnam: 'ปวช.(สอจ.)' }, + { dtlcod: 'BDG030', dtlnam: 'โครงการพัฒนาศักยภาพผู้เรียนอาชีวศึกษาในการเป็นผู้ประกอบการ (บ่มเพาะ)' }, + { dtlcod: 'BDG031', dtlnam: 'โครงการพัฒนาและยกระดับการติดตามผู้สำเร็จการศึกษาอาชีวศึกษา' }, + { dtlcod: 'BDG032', dtlnam: 'โครงการเสริมสร้างคุณธรรม จริยธรรมและธรรมาภิบาลในสถานศึกษา' }, + { dtlcod: 'BDG033', dtlnam: 'โครงการจัดการอาชีวศึกษาเพื่อสนองพระราชดำริ' }, + { dtlcod: 'BDG034', dtlnam: 'เงินรายได้ ป.ตรี' }, + { dtlcod: 'BDG035', dtlnam: 'งบดำเนินงาน 235200' } + ] +}; + + +ngOnInit(): void { + this.setupForm(); +} + +setupForm() { + this.addItemForm = new FormGroup({ + category: new FormControl('', [Validators.required]), + name: new FormControl('', [Validators.required]), + qty: new FormControl(1, [Validators.required, Validators.min(1)]), + price: new FormControl(0, [Validators.required, Validators.min(1)]) + }); +} + +addBudgetItem() { + if (this.addItemForm.invalid) { + this.addItemForm.markAllAsTouched(); + return; + } + + const formValue = this.addItemForm.value; + + this.budgetItems.push({ + code: 'NEW' + (this.budgetItems.length + 1).toString().padStart(3, '0'), + name: formValue.name, + qty: formValue.qty, + price: formValue.price, + // category: formValue.category + }); + + // reset form + this.addItemForm.reset({ + category: '', + name: '', + qty: 1, + price: 0 + }); +} + +getTotalAmount() { + return this.budgetItems.reduce((sum, item) => sum + item.qty * item.price, 0); +} + +} diff --git a/ng-ttc-frontend/src/app/component/main-dashboard/main-dashboard.component.css b/ng-ttc-frontend/src/app/component/main-dashboard/main-dashboard.component.css index 70db525..f9e1370 100644 --- a/ng-ttc-frontend/src/app/component/main-dashboard/main-dashboard.component.css +++ b/ng-ttc-frontend/src/app/component/main-dashboard/main-dashboard.component.css @@ -643,4 +643,4 @@ max-height: 25rem; overflow-y: auto; padding-right: 0.5rem; -} \ No newline at end of file +} diff --git a/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.css b/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.css new file mode 100644 index 0000000..e69de29 diff --git a/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.html b/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.html new file mode 100644 index 0000000..275fd54 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.html @@ -0,0 +1,107 @@ +
+
+

หน้าหลัก ( landing )

+
+ + + + + + + + +
+ +
+
+
+ + +
+
+
+

เมนู

+
+
+ + + + การเบิกงวดงบ +
+ +
+ + + + สัญญา / ข้อตกลง +
+ +
+ + + การอนุมัติโครงการ +
+ +
+ + + + เอกสารฟอร์มวิทยาลัย +
+ +
+ + + จัดสรรงบประมาณ +
+ +
+ + + + วิเคราะห์ & รายงาน +
+
+
+
+ +
+
+

กล่องแจ้งเตือน

+
+
+
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+

อัพเดตซอฟต์แวร์

+
+
+
+
+
+
+
+ +
diff --git a/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.ts b/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.ts new file mode 100644 index 0000000..12414c8 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/main-landing/main-landing.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-main-landing', + standalone: false, + templateUrl: './main-landing.component.html', + styleUrls: ['./main-landing.component.css'] +}) +export class MainLandingComponent implements OnInit { + + constructor( + + ) {} + + ngOnInit() { + } + +} diff --git a/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.css b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.css new file mode 100644 index 0000000..70db525 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.css @@ -0,0 +1,646 @@ +:host { + display: block; + padding: 2rem clamp(1.25rem, 4vw, 3rem) 3rem; + background: radial-gradient(120% 120% at 0% 0%, #f6f8ff 0%, #eef5ff 55%, #ffffff 100%); + min-height: 100%; +} + +.dashboard { + display: flex; + flex-direction: column; + gap: 2rem; + max-width: 1280px; + margin: 0 auto; +} + +.dashboard__hero { + background: #0f172a; + color: #f8fafc; + padding: 2rem; + border-radius: 28px; + display: flex; + flex-wrap: wrap; + gap: 1.5rem; + justify-content: space-between; + align-items: center; + box-shadow: 0 20px 50px rgba(15, 23, 42, 0.3); +} + +.hero__text h1 { + margin: 0 0 0.5rem; + font-size: clamp(1.8rem, 3vw, 2.5rem); +} + +.hero__subtitle { + margin: 0; + color: rgba(248, 250, 252, 0.7); +} + +.eyebrow { + text-transform: uppercase; + letter-spacing: 0.12em; + font-size: 0.8rem; + color: rgba(248, 250, 252, 0.8); + margin: 0 0 0.5rem; +} + +.hero__actions { + display: flex; + gap: 0.75rem; + flex-wrap: wrap; +} + +.btn { + border: none; + border-radius: 999px; + padding: 0.65rem 1.5rem; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.btn--primary { + background: linear-gradient(135deg, #22d3ee, #0ea5e9); + color: #0f172a; + box-shadow: 0 15px 30px rgba(14, 165, 233, 0.35); +} + +.btn--ghost { + background: rgba(248, 250, 252, 0.12); + color: #f8fafc; + border: 1px solid rgba(248, 250, 252, 0.2); +} + +.btn--compact { + padding: 0.45rem 1.15rem; + font-size: 0.9rem; +} + +.btn:focus-visible { + outline: 3px solid rgba(14, 165, 233, 0.4); + outline-offset: 3px; +} + +.btn:hover { + transform: translateY(-1px); +} + +.dashboard__stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); + gap: 1rem; +} + +.dashboard__periods { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 1rem; +} + +.period-card { + background: rgba(15, 23, 42, 0.85); + color: #f8fafc; + border-radius: 22px; + padding: 1.25rem 1.5rem; + display: flex; + flex-direction: column; + gap: 1rem; + box-shadow: 0 18px 35px rgba(15, 23, 42, 0.4); +} + +.period-card__header { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.9rem; + color: rgba(248, 250, 252, 0.75); +} + +.period-card__badge { + padding: 0.2rem 0.75rem; + border-radius: 999px; + font-size: 0.8rem; + font-weight: 600; + text-transform: uppercase; +} + +.period-card__badge--year { background: rgba(248, 250, 252, 0.14); } +.period-card__badge--month { background: rgba(125, 211, 252, 0.25); } +.period-card__badge--week { background: rgba(110, 231, 183, 0.2); } + +.period-card__values { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.75rem; +} + +.muted { + margin: 0; + font-size: 0.8rem; + color: rgba(248, 250, 252, 0.65); +} + +.income, +.expense, +.net { + margin: 0.1rem 0 0; + font-size: 1.2rem; + font-weight: 600; +} + +.income { color: #34d399; } +.expense { color: #fbbf24; } +.net { color: #38bdf8; } + +.trend-chip { + background: rgba(248, 250, 252, 0.12); + padding: 0.35rem 0.9rem; + border-radius: 999px; + font-size: 0.85rem; + font-weight: 600; + align-self: flex-start; +} + +.stat-card { + background: #ffffff; + border-radius: 20px; + padding: 1.25rem; + display: flex; + gap: 1rem; + align-items: center; + box-shadow: 0 8px 30px rgba(15, 23, 42, 0.08); +} + +.stat-card__icon { + width: 52px; + height: 52px; + border-radius: 16px; + flex-shrink: 0; + background: #e2e8f0; +} + +.accent-mint { background: linear-gradient(135deg, #a7f3d0, #34d399); } +.accent-lavender { background: linear-gradient(135deg, #ddd6fe, #a78bfa); } +.accent-amber { background: linear-gradient(135deg, #fde68a, #fbbf24); } +.accent-teal { background: linear-gradient(135deg, #99f6e4, #14b8a6); } + +.stat-card__label { + margin: 0; + color: #475569; + font-size: 0.9rem; +} + +.stat-card__value { + font-size: 1.5rem; + font-weight: 700; + color: #0f172a; +} + +.stat-card__trend { + margin: 0; + color: #64748b; + font-size: 0.85rem; +} + +.dashboard__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 1.5rem; +} + +.panel { + background: #ffffff; + border-radius: 24px; + padding: 1.5rem; + box-shadow: 0 12px 35px rgba(15, 23, 42, 0.08); + display: flex; + flex-direction: column; + gap: 1.2rem; +} + +.panel--main { + grid-column: span 2; + min-height: 280px; +} + +.panel--side { + grid-column: span 1; +} + +@media (max-width: 900px) { + .panel--main { + grid-column: span 1; + } +} + +.panel__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.panel__header h2 { + margin: 0; + font-size: 1.2rem; +} + +.panel__header p { + margin: 0; + color: #94a3b8; + font-size: 0.9rem; +} + +.ledger-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 1.5rem; +} + +.quick-log__form { + display: flex; + flex-direction: column; + gap: 0.9rem; +} + +.quick-log__form label { + display: flex; + flex-direction: column; + gap: 0.4rem; + font-size: 0.9rem; + color: #475569; +} + +.quick-log__form input, +.quick-log__form textarea { + border: 1px solid #e2e8f0; + border-radius: 14px; + padding: 0.75rem 1rem; + font-family: inherit; + font-size: 0.95rem; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.quick-log__form input:focus, +.quick-log__form textarea:focus { + border-color: #0ea5e9; + box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.15); + outline: none; +} + +.quick-log__grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.85rem; +} + +.quick-log__toggle { + display: inline-flex; + gap: 0.4rem; + background: #f1f5f9; + border-radius: 999px; + padding: 0.25rem; +} + +.toggle-btn { + border: none; + background: transparent; + border-radius: 999px; + padding: 0.4rem 1.1rem; + font-weight: 600; + color: #475569; + cursor: pointer; +} + +.toggle-btn.is-active { + background: #0ea5e9; + color: #f8fafc; +} + +.ledger-table { + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.pie-panel__content { + display: grid; + grid-template-columns: minmax(220px, 1fr) 1fr; + gap: 2rem; + align-items: center; +} + +.pie-chart { + width: 220px; + height: 220px; + border-radius: 50%; + position: relative; + margin: 0 auto; + box-shadow: inset 0 0 20px rgba(15, 23, 42, 0.08); +} + +.pie-chart__center { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 120px; + border-radius: 50%; + background: #ffffff; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + box-shadow: 0 10px 25px rgba(15, 23, 42, 0.1); +} + +.pie-chart__center p { + margin: 0; + font-size: 0.85rem; + color: #94a3b8; +} + +.pie-chart__center strong { + font-size: 1.2rem; + color: #0f172a; +} + +.pie-legend { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.pie-legend__item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.4rem 0; +} + +.swatch { + width: 14px; + height: 14px; + border-radius: 4px; +} + +.pie-legend__label { + margin: 0; + font-weight: 600; + color: #0f172a; +} + +.pie-legend__value { + margin: 0; + color: #94a3b8; + font-size: 0.85rem; +} + +.ledger-row { + display: grid; + grid-template-columns: 2fr 1fr 0.8fr 1.2fr; + gap: 1rem; + align-items: center; + padding: 0.75rem 0.4rem; + border-bottom: 1px solid #e2e8f0; +} + +.ledger-head { + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.08em; + color: #94a3b8; +} + +.ledger-main { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.pill { + padding: 0.2rem 0.7rem; + border-radius: 999px; + font-size: 0.8rem; + font-weight: 600; +} + +.pill--income { + background: rgba(16, 185, 129, 0.12); + color: #059669; +} + +.pill--expense { + background: rgba(248, 113, 113, 0.15); + color: #dc2626; +} + +.ledger-title { + margin: 0; + font-weight: 600; +} + +.ledger-date { + margin: 0; + font-size: 0.85rem; + color: #94a3b8; +} + +.ledger-category { + font-weight: 500; + color: #475569; +} + +.ledger-amount { + font-weight: 700; +} + +.ledger-note { + color: #64748b; + font-size: 0.9rem; +} + +.trend-chart { + display: flex; + gap: 1rem; + align-items: flex-end; + min-height: 180px; +} + +.trend-chart__bar { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; +} + +.trend-chart__value { + width: 100%; + border-radius: 16px 16px 6px 6px; + background: linear-gradient(180deg, rgba(14, 165, 233, 0.8) 0%, rgba(56, 189, 248, 0.4) 100%); +} + +.trend-chart__label { + font-size: 0.85rem; + color: #475569; +} + +.ratio-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.ratio { + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 18px; + padding: 0.85rem 1.2rem; + font-weight: 600; +} + +.ratio--positive { + background: rgba(16, 185, 129, 0.12); + color: #047857; +} + +.ratio--neutral { + background: rgba(59, 130, 246, 0.12); + color: #1d4ed8; +} + +.ratio--warning { + background: rgba(251, 191, 36, 0.15); + color: #b45309; +} + +.alerts-panel .alert { + display: flex; + justify-content: space-between; + align-items: center; + background: #f8fafc; + border-radius: 18px; + padding: 1rem 1.2rem; + gap: 1rem; +} + +.alert__title { + margin: 0 0 0.3rem; + font-weight: 600; + color: #0f172a; +} + +.alert__detail { + margin: 0; + color: #64748b; + font-size: 0.9rem; +} + +.alert__tag { + padding: 0.4rem 0.9rem; + border-radius: 999px; + background: #e0f2fe; + color: #0369a1; + font-size: 0.85rem; + font-weight: 600; +} + +.task-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.85rem; +} + +.task { + background: #f8fafc; + border-radius: 18px; + padding: 1rem 1.2rem; + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; +} + +.task__title { + margin: 0 0 0.25rem; + font-weight: 600; +} + +.task__due { + margin: 0; + color: #94a3b8; + font-size: 0.9rem; +} + +.task__badge { + padding: 0.35rem 0.8rem; + border-radius: 12px; + background: #e2e8f0; + font-weight: 600; +} + +.is-credit { + color: #10b981; + font-weight: 600; +} + +.is-debit { + color: #ef4444; + font-weight: 600; +} + +@media (max-width: 640px) { + .dashboard__hero, + .panel { + padding: 1.25rem; + } + + .quick-log__grid { + grid-template-columns: 1fr; + } + + .pie-panel__content { + grid-template-columns: 1fr; + } + + .pie-chart { + width: 180px; + height: 180px; + } + + .ledger-row { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .ledger-row span:nth-child(3), + .ledger-row span:nth-child(4) { + text-align: left; + } +} + +.quick-log__form select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; +} + +.ledger-table.is-scrollable { + max-height: 25rem; + overflow-y: auto; + padding-right: 0.5rem; +} \ No newline at end of file diff --git a/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.html b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.html new file mode 100644 index 0000000..277c5a3 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.html @@ -0,0 +1,152 @@ +
+ + +
+ +
+
งบทั้งหมด
+
+ {{ totalBudget | number:'1.0-2' }} บาท +
+
+ +
+
งบที่อนุมัติแล้ว
+
+ {{ approvedBudget | number:'1.0-2' }} บาท +
+
+ +
+
งบคงเหลือ
+
+ {{ remainingBudget | number:'1.0-2' }} บาท +
+
+ +
+ + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับรหัสโครงการชื่อโครงการผู้รับผิดชอบงบที่ขออนุมัติหมวดงบจำนวนที่อนุมัติสถานะดำเนินการ
{{ i + 1 }} + {{ p.code }} + + {{ p.name }} + + {{ p.owner }} + + {{ p.budget | number:'1.0-0' }} บาท + + + + + + + อนุมัติแล้ว + รออนุมัติ + ไม่อนุมัติ + + + + + + +
+ +
+ + + +
diff --git a/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.ts b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.ts new file mode 100644 index 0000000..17e33f2 --- /dev/null +++ b/ng-ttc-frontend/src/app/component/main-manager/main-manager.component.ts @@ -0,0 +1,168 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms'; +import { GeneralService } from '../../services/generalservice'; +import { IDropAct, IStateDrop, IStateResultResponse, IActData, IActSumData } from '../../interfaces/dashboard.interface' +import { DashboardStateService } from '../../services/state/dashboard-state.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-main-manager', + standalone: false, + templateUrl: './main-manager.component.html', + styleUrl: './main-manager.component.css' +}) +export class MainManagerComponent implements OnInit { + + mode: string = 'i'; + + totalBudget = 200000; // งบทั้งหมด + approvedBudget = 65000; // งบที่อนุมัติแล้ว + + + + get remainingBudget() { + return this.totalBudget - this.approvedBudget; + } + + + + projects = [ + { code: 'PRJ001', name: 'ระบบจัดการน้ำดื่ม', owner: 'นาย A', budget: 20000, status: 'WAIT' }, + { code: 'PRJ002', name: 'ปรับปรุงอาคาร B', owner: 'นางสาว B', budget: 45000, status: 'WAIT' }, + { code: 'PRJ003', name: 'ซื้อคอมพิวเตอร์', owner: 'นาย C', budget: 30000, status: 'APPROVED' } + ]; + + approveProject(p: any) { + p.status = 'APPROVED'; + this.approvedBudget += p.budget; + } + + rejectProject(p: any) { + p.status = 'REJECTED'; + } + + openBudgetDetail(project: any) { + this.router.navigate(['/main/manager/budget', project.code]); + } + + + + budgetCategoriesDrop = { + expense: [ + { dtlcod: 'BDG001', dtlnam: 'เงินรายได้' }, + { dtlcod: 'BDG002', dtlnam: 'งบดำเนินงาน ปวส.' }, + { dtlcod: 'BDG003', dtlnam: 'โครงการส่งเสริมพัฒนาทักษะวิชาชีพทักษะพื้นฐาน' }, + { dtlcod: 'BDG004', dtlnam: 'ค่ากิจกรรมพัฒนาคุณภาพผู้เรียน' }, + { dtlcod: 'BDG005', dtlnam: 'อุดหนุนส่งเสริมและพัฒนาผู้เรียนองค์การวิชาชีพแห่งประเทศไทย (อวท.)' }, + { dtlcod: 'BDG006', dtlnam: 'งบดำเนินงาน ระยะสั้น' }, + { dtlcod: 'BDG007', dtlnam: 'โครงการบูรณาการการพัฒนาทักษะทางวิชาชีพกับการเสริมสร้างคุณลักษณะอันพึงประสงค์ (FIX IT)' }, + { dtlcod: 'BDG008', dtlnam: 'โครงการพัฒนาทักษะและสมรรถนะวิชาชีพกำลังคน (Up-skill, Re-skill)' }, + { dtlcod: 'BDG009', dtlnam: 'งบดำเนินงาน ปวช.' }, + { dtlcod: 'BDG010', dtlnam: 'โครงการขยายและยกระดับการจัดอาชีวศึกษาระบบทวิภาคีคุณภาพสูง' }, + { dtlcod: 'BDG011', dtlnam: 'ปวช.(สอจ)' }, + { dtlcod: 'BDG012', dtlnam: 'ค่าจัดการเรียนการสอน' }, + { dtlcod: 'BDG013', dtlnam: 'งบดำเนินงาน 170000' }, + { dtlcod: 'BDG014', dtlnam: 'โครงการพัฒนาทักษะและศักยภาพภาพการจัดการเรียนการสอนอาชีวศึกษา' }, + { dtlcod: 'BDG015', dtlnam: 'ศึกษาธิการ' }, + { dtlcod: 'BDG016', dtlnam: 'Up-skill' }, + { dtlcod: 'BDG017', dtlnam: 'ติดตามผู้สำเร็จ' }, + { dtlcod: 'BDG018', dtlnam: 'ทวิภาคี' }, + { dtlcod: 'BDG019', dtlnam: 'พันธุกรรม' }, + { dtlcod: 'BDG020', dtlnam: 'ปวส(สาธารณูประโภค)' }, + { dtlcod: 'BDG021', dtlnam: 'ปวส(ค่าสาธารณูปโภค)' }, + { dtlcod: 'BDG022', dtlnam: 'งบดำเนินงาน (ค่าสาธารณูปโภค)' }, + { dtlcod: 'BDG023', dtlnam: 'ค่าหนังสือเรียน' }, + { dtlcod: 'BDG024', dtlnam: 'โครงการอาชีวะต้านยาเสพติด' }, + { dtlcod: 'BDG025', dtlnam: 'ค่าตอบแทนพนักงานราชการ' }, + { dtlcod: 'BDG026', dtlnam: 'ค่าอุปกรณ์การเรียน' }, + { dtlcod: 'BDG027', dtlnam: 'โครงการยกระดับและพัฒนาขีดความสามารถด้านภาษาและทักษะดิจิทัลเพื่อพัฒนากำลังคนให้มีสมรรถนะสูง' }, + { dtlcod: 'BDG028', dtlnam: 'โครงการอนุรักษ์พันธุกรรมพืชอันเนื่องมาจากพระราชดำริ' }, + { dtlcod: 'BDG029', dtlnam: 'ปวช.(สอจ.)' }, + { dtlcod: 'BDG030', dtlnam: 'โครงการพัฒนาศักยภาพผู้เรียนอาชีวศึกษาในการเป็นผู้ประกอบการ (บ่มเพาะ)' }, + { dtlcod: 'BDG031', dtlnam: 'โครงการพัฒนาและยกระดับการติดตามผู้สำเร็จการศึกษาอาชีวศึกษา' }, + { dtlcod: 'BDG032', dtlnam: 'โครงการเสริมสร้างคุณธรรม จริยธรรมและธรรมาภิบาลในสถานศึกษา' }, + { dtlcod: 'BDG033', dtlnam: 'โครงการจัดการอาชีวศึกษาเพื่อสนองพระราชดำริ' }, + { dtlcod: 'BDG034', dtlnam: 'เงินรายได้ ป.ตรี' }, + { dtlcod: 'BDG035', dtlnam: 'งบดำเนินงาน 235200' } + ] +}; + + // isModalOpen: boolean = false; + // isSubmitting: boolean = false; + // arrearsForm!: FormGroup; + // saveFrm!: FormGroup; + // myActData: IActData[] = []; + // // myDropAct: IStateDrop[] = []; + // myDropAct: IStateDrop = { income: [], expense: [] }; + // myActSumData: IActSumData = { + // summary: { + // totalIncome: '', + // totalExpense: '', + // netProfit: '', + // profitRate: '', + // adjustedProfitRate: '', + // period: '' + // }, + // pie: { + // income: [], + // expense: [] + // } + // }; + // ActSumDataGradient: any + + + // readonly ownerName = 'Nuttakit'; + + constructor( + private router: Router + ) {} + + + + + ngOnInit(): void { + this.setupFormControl(); + // this.dashboardStateService.getStateResult().subscribe(data => { + // if (data) { + // this.myDropAct = data; + // } + // }); + // // ผลลับท์ ของ รายการ + // this.dashboardStateService.getStateAccountResult().subscribe(data => { + // if (data) { + // this.myActData = data; + // } + // }); + // // ผลลัพการ คำนวณ ของ ปัญชี ต่างๆ + // this.dashboardStateService.getStateSumResult().subscribe(data => { + // if (data) { + // this.myActSumData = data; + // this.ActSumDataGradient = this.buildExpenseGradient() + // } + // }); + } + setupFormControl(){ + // this.arrearsForm = new FormGroup({ + // // email: new FormControl('',[Validators.required, Validators.email, Validators.maxLength(100)]), + // amount: new FormControl('',[Validators.required, Validators.maxLength(20)]), + // expdtm: new FormControl('',[Validators.required, Validators.maxLength(12)]), + // note: new FormControl('',[Validators.maxLength(200)]), + // reason: new FormControl('',[Validators.required, Validators.maxLength(200)]) + // }); + + // this.saveFrm = new FormGroup({ + // actacpdtm: new FormControl('',[Validators.required, Validators.maxLength(12)]), + // actqty: new FormControl('',[Validators.required]), + // actcat: new FormControl('',[Validators.required, Validators.maxLength(1)]), + // actcmt: new FormControl('',[Validators.maxLength(200)]) + // }); + } + + onSaveSubmit(){ + + } + + onArrearsSubmit(){ + + } +} diff --git a/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html b/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html index f920b7a..1ab33a0 100644 --- a/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html +++ b/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html @@ -10,33 +10,54 @@

- Global Sidebar +

+ + +

diff --git a/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.css b/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.css new file mode 100644 index 0000000..e69de29 diff --git a/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.html b/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.html new file mode 100644 index 0000000..5e40efe --- /dev/null +++ b/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.html @@ -0,0 +1,2 @@ + + diff --git a/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.ts b/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.ts new file mode 100644 index 0000000..8c34ecf --- /dev/null +++ b/ng-ttc-frontend/src/app/content/main-manager-content/main-manager-content.component.ts @@ -0,0 +1,162 @@ +import { DashboardStateService } from '../../services/state/dashboard-state.service'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ChartConfiguration, ChartOptions } from 'chart.js'; +import { BaseChartDirective } from 'ng2-charts'; +import { GeneralService } from '../../services/generalservice'; +import { IDropAct, IStateDrop, IActData, IActSumData } from '../../interfaces/dashboard.interface'; + + +@Component({ + selector: 'app-main-manager-content', + standalone: false, + templateUrl: './main-manager-content.component.html', + styleUrls: ['./main-manager-content.component.css'] +}) +export class MainManagerContentComponent implements OnInit { + // @ViewChild(BaseChartDirective) chart?: BaseChartDirective; + myDropAct!: IStateDrop; + myActData: IActData[] = []; + myActSumData: IActSumData = { + summary: { + totalIncome: '', + totalExpense: '', + netProfit: '', + profitRate: '', + adjustedProfitRate: '', + period: '' + }, + pie: { + income: [], + expense: [] + } + }; + + constructor( + private generalService: GeneralService, + private dashboardStateService: DashboardStateService + ) {} + + ngOnInit(): void { + let token = localStorage.getItem('access_token') + this.OnSearchAct(token, true); + this.OnSetupDashboard(token, true); + this.OnSearchSum(token, true); + } + + OnSearchAct(value: any, setupFirst: boolean): void { + const uri = '/api/web/accountingSearch'; + let request = { + token: value + } + this.generalService.postRequest(uri, request).subscribe({ + next: (result: any) => { + if (result.code === '200') { + this.generalService.trowApi(result); + this.myActData = result.data; + this.dashboardStateService.setStateAccountResult(this.myActData); + }else{ + this.generalService.trowApi(result); + } + }, + error: (error: any) => { + this.generalService.trowApi(error); + }, + complete: () => { + + } + }); + } + + + + OnSetupDashboard(value: any, setupFirst: boolean): void { + const uri = '/api/web/accountingSetup'; + let request = { + token: value + } + this.generalService.postRequest(uri, request).subscribe({ + next: (result: any) => { + if (result.code === '200') { + this.generalService.trowApi(result); + this.myDropAct = result.data + this.dashboardStateService.setStateResult(this.myDropAct) + }else{ + this.generalService.trowApi(result); + } + }, + error: (error: any) => { + this.generalService.trowApi(error); + }, + complete: () => { + + } + }); + } + + OnSearchSum(value: any, setupFirst: boolean): void { + const uri = '/api/web/accountingSum'; + let request = { + token: value + } + this.generalService.postRequest(uri, request).subscribe({ + next: (result: any) => { + if (result.code === '200') { + this.generalService.trowApi(result); + this.myActSumData = result.data + this.dashboardStateService.setStateSumResult(this.myActSumData); + }else{ + this.generalService.trowApi(result); + } + }, + error: (error: any) => { + this.generalService.trowApi(error); + }, + complete: () => { + + } + }); + } + + // fetchChartData(): void { + // // NOTE: Using a placeholder endpoint as the actual one was not provided. + // const uri = '/api/dashboard/summary-last-6-months'; + + // this.generalService.getRequest(uri).subscribe({ + // next: (result: any) => { + // if (result.code === '200' && result.data) { + // this.processChartData(result.data); + // } else { + // console.warn('Could not fetch chart data:', result.message_th); + // // Optionally, display placeholder data or an error message + // this.setupPlaceholderData(); + // } + // }, + // error: (error: any) => { + // console.error('Error fetching chart data:', error); + // // Display placeholder data on error to show the graph structure + // this.setupPlaceholderData(); + // } + // }); + // } + + // processChartData(data: any[]): void { + // const labels = data.map(item => item.month); + // const revenues = data.map(item => item.revenue); + + // this.lineChartData.labels = labels; + // this.lineChartData.datasets[0].data = revenues; + + // this.chart?.update(); + // } + + // setupPlaceholderData(): void { + // // This function is called if the API fails, to show a sample graph. + // const labels = ['January', 'February', 'March', 'April', 'May', 'June']; + // const revenues = [1200, 1900, 3000, 5000, 2300, 3200]; // Sample data + + // this.lineChartData.labels = labels; + // this.lineChartData.datasets[0].data = revenues; + + // this.chart?.update(); + // } +} diff --git a/ng-ttc-frontend/src/app/controls/main-control/main-control-routing.module.ts b/ng-ttc-frontend/src/app/controls/main-control/main-control-routing.module.ts index 285e146..3b0629d 100644 --- a/ng-ttc-frontend/src/app/controls/main-control/main-control-routing.module.ts +++ b/ng-ttc-frontend/src/app/controls/main-control/main-control-routing.module.ts @@ -1,7 +1,10 @@ +import { MainManagerContentComponent } from './../../content/main-manager-content/main-manager-content.component'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { MainDashboardContentComponent } from '../../content/main-dashboard-content/main-dashboard-content.component'; import { MainReportComponent } from '../../component/main-report/main-report.component'; +import { BudgetAproval } from '../../component/budget-aproval/budget-aproval'; +import { MainLandingComponent } from '../../component/main-landing/main-landing.component'; // import { MainReportComponent } from '../../component/main-report/main-report.component'; @@ -9,6 +12,15 @@ import { MainReportComponent } from '../../component/main-report/main-report.com const routes: Routes = [ { path: 'dashboard', component: MainDashboardContentComponent }, { path: 'report', component: MainReportComponent }, + { path: 'landing', component: MainLandingComponent }, + { path: 'manager', component: MainManagerContentComponent }, + { + path: 'manager', + children: [ + { path: '', component: MainManagerContentComponent }, // รายการโครงการ + { path: 'budget/:code', component: BudgetAproval }, // จัดการงบประมาณ + ] + }, // children: [ // { // path: 'dashboard', @@ -18,8 +30,8 @@ const routes: Routes = [ // { path: '', redirectTo: 'profile', pathMatch: 'full' } // ] - { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, - { path: '**', redirectTo: 'dashboard' } + { path: '', redirectTo: 'landing', pathMatch: 'full' }, + { path: '**', redirectTo: 'landing' } ]; @NgModule({ diff --git a/ng-ttc-frontend/src/app/controls/main-control/main-control.module.ts b/ng-ttc-frontend/src/app/controls/main-control/main-control.module.ts index ce71e45..9e53d4a 100644 --- a/ng-ttc-frontend/src/app/controls/main-control/main-control.module.ts +++ b/ng-ttc-frontend/src/app/controls/main-control/main-control.module.ts @@ -1,3 +1,4 @@ +import { MainManagerContentComponent } from './../../content/main-manager-content/main-manager-content.component'; import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; // import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @@ -10,6 +11,9 @@ import { MainDashboardComponent } from '../../component/main-dashboard/main-dash import { MainDashboardContentComponent } from '../../content/main-dashboard-content/main-dashboard-content.component'; import { AccDateFormatPipe } from '../../pipe/dtmtodatetime.pipe'; import { MainReportComponent } from '../../component/main-report/main-report.component'; +import { MainManagerComponent } from '../../component/main-manager/main-manager.component'; +import { BudgetAproval } from '../../component/budget-aproval/budget-aproval'; +import { MainLandingComponent } from '../../component/main-landing/main-landing.component'; // import { MainReportComponent } from '../../component/main-report/main-report.component'; @@ -20,6 +24,10 @@ import { MainReportComponent } from '../../component/main-report/main-report.com MainDashboardComponent, MainDashboardContentComponent, MainReportComponent, + MainManagerContentComponent, + MainManagerComponent, + BudgetAproval, + MainLandingComponent, AccDateFormatPipe // MainReportComponent ], diff --git a/ng-ttc-frontend/src/index.html b/ng-ttc-frontend/src/index.html index c6f97e2..43c87cd 100644 --- a/ng-ttc-frontend/src/index.html +++ b/ng-ttc-frontend/src/index.html @@ -2,7 +2,7 @@ - AccountingNgNuttakit + TTC diff --git a/ng-ttc-frontend/src/styles.css b/ng-ttc-frontend/src/styles.css index ddfe0d5..165eee0 100644 --- a/ng-ttc-frontend/src/styles.css +++ b/ng-ttc-frontend/src/styles.css @@ -72,6 +72,8 @@ html, body, app-root { } + + /* sensible default box model */ *, *::before, *::after { box-sizing: border-box; } @@ -219,3 +221,45 @@ body { font-weight: 900; font-style: italic; } + + +/* Custom-Table */ +.ledger-table { + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.ledger-table.is-scrollable { + max-height: 25rem; + overflow-y: auto; + padding-right: 0.5rem; +} + + +.ledger-row { + display: grid; + grid-template-columns: 2fr 1fr 0.8fr 1.2fr; + gap: 1rem; + align-items: center; + padding: 0.75rem 0.4rem; + border-bottom: 1px solid #e2e8f0; +} + + +.ledger-row { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.ledger-row span:nth-child(3), +.ledger-row span:nth-child(4) { + text-align: left; +} + + +.ledger-head { + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.08em; + color: #94a3b8; +} diff --git a/ng-ttc-frontend/tailwind.config.js b/ng-ttc-frontend/tailwind.config.js new file mode 100644 index 0000000..8974f83 --- /dev/null +++ b/ng-ttc-frontend/tailwind.config.js @@ -0,0 +1,10 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{html,ts}", + ], + theme: { + extend: {}, + }, + plugins: [], +}