From 40e682e5d8569e1df1f4e8290e6186d6702a8407 Mon Sep 17 00:00:00 2001 From: x2Skyz Date: Sun, 30 Nov 2025 23:47:29 +0700 Subject: [PATCH] -downloads -subscribe project --- .../main-manager/main-manager.component.html | 28 ++-- .../main-manager/main-manager.component.ts | 5 + .../component/main-project/main-project.html | 120 ++++++++++-------- .../component/main-project/main-project.ts | 18 +++ .../component/sidebar/sidebar.component.html | 10 +- .../main-manager-content.component.html | 2 +- .../main-manager-content.component.ts | 39 ++++++ .../src/app/interfaces/main.interface.ts | 1 + .../src/app/pipe/dtmtodatetime.pipe.ts | 6 +- .../src/app/services/generalservice.ts | 41 ++++-- 10 files changed, 193 insertions(+), 77 deletions(-) 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 index e257cbc..fd766a2 100644 --- 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 @@ -90,13 +90,25 @@ - +
+ + + + + +
@@ -118,7 +130,7 @@
แสดง {{ myPrjMst.length }} รายการ
-
+ 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 index 5f6343e..5c7dfff 100644 --- 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 @@ -12,6 +12,7 @@ import { Router } from '@angular/router'; styleUrl: './main-manager.component.css' }) export class MainManagerComponent implements OnInit { + @Output() documentDownload = new EventEmitter(); mode: string = 'i'; @@ -60,6 +61,10 @@ export class MainManagerComponent implements OnInit { } }); } + + OnDocumentDownload(prjseq: number){ + this.documentDownload.emit(prjseq); + } setupFormControl(){ } diff --git a/ng-ttc-frontend/src/app/component/main-project/main-project.html b/ng-ttc-frontend/src/app/component/main-project/main-project.html index 0b22c58..8432839 100644 --- a/ng-ttc-frontend/src/app/component/main-project/main-project.html +++ b/ng-ttc-frontend/src/app/component/main-project/main-project.html @@ -40,13 +40,13 @@ 'text-red-600': item.prjcomstt === 'CN' }"> @if(item.prjcomstt === 'UAC'){ รออนุมัติ } - @else if(item.prjcomstt === 'BAP'){ อนุมัติแล้ว } + @else if(item.prjcomstt === 'BAP'){ จัดสรรงบประมาณแล้ว } @else if(item.prjcomstt === 'CN'){ ไม่อนุมัติ } @else { {{ item.prjcomstt }} } - + } @empty { @@ -58,68 +58,86 @@ + + @for (idx of subscribeData; track $index) { +
+

ความคืบหน้าโครงการ: {{ idx.prjnam }}

-
-

ความคืบหน้าโครงการ: โครงการปรับปรุงอาคาร

+
-
+
+
+
+ + + +
+
+
+

1. ยื่นคำขอโครงการ

+

วันที่: {{ (idx.prjacpdtm ?? '-') | dtmtodatetime}}

+

เอกสารและรายละเอียดโครงการครบถ้วน

+
+
-
+
-
- - - -
-
-
-

1. ยื่นคำขอโครงการ

-

วันที่: 10/11/2568

-

เอกสารและรายละเอียดโครงการครบถ้วน

-
-
- -
-
-
+
2
-
+
+
-

2. พิจารณางบประมาณ

-

กำหนดแล้วเสร็จ: 25/11/2568

-

รอฝ่ายบัญชีและงบประมาณอนุมัติยอดจัดสรร

+

+ 2. พิจารณางบประมาณ +

+

กำหนดแล้วเสร็จ: {{ (idx.trnacpdtm ?? '-') | dtmtodatetime }}

+ + @if(idx.prjcomstt === 'BAP') { +

ได้รับอนุมัติงบประมาณเรียบร้อยแล้ว

+ } @else if(idx.prjcomstt === 'CN') { +

โครงการไม่ผ่านการอนุมัติ

+ } @else { +

รอฝ่ายแผนและงบประมาณอนุมัติยอดจัดสรร

+ } +
-
-
-
- 3 -
-
-
-

3. อนุมัติโดยผู้บริหาร

-

ยังไม่ระบุวันที่

-

รอขั้นตอนก่อนหน้าเสร็จสิ้น

-
-
+
+
+
+ 3 +
+
+
+

3. อนุมัติโดยผู้บริหาร

+

ยังไม่ระบุวันที่

+

รอขั้นตอนก่อนหน้าเสร็จสิ้น

+
+
-
-
-
- 4 -
-
-
-

4. จัดสรรงบประมาณสำเร็จ

-

ยังไม่ระบุวันที่

-
-
+
+
+
+ 4 +
+
+
+

4. จัดสรรงบประมาณสำเร็จ

+

ยังไม่ระบุวันที่

+
+
-
-
+
+
+ } @empty { +
+

กรุณาเลือกโครงการที่จะแสดง

+
+ }
diff --git a/ng-ttc-frontend/src/app/component/main-project/main-project.ts b/ng-ttc-frontend/src/app/component/main-project/main-project.ts index 8da56e7..1507df8 100644 --- a/ng-ttc-frontend/src/app/component/main-project/main-project.ts +++ b/ng-ttc-frontend/src/app/component/main-project/main-project.ts @@ -17,6 +17,7 @@ import { ProjectStateService } from '../../services/state/project-state.service' export class MainProject implements OnInit { myPrjMst: IPrjMst[] = []; // ตัวแปรเก็บข้อมูลโครงการ + subscribeData: IPrjMst[] = []; constructor( private generalService: GeneralService, @@ -54,6 +55,23 @@ export class MainProject implements OnInit { // }); // } + onSubscribePrj(item: any) { + // 1. เช็คว่า item นี้ เป็นตัวเดิมที่ติดตามอยู่แล้วหรือไม่? + const isAlreadySubscribed = this.subscribeData.some(sub => sub.prjseq === item.prjseq); + + if (isAlreadySubscribed) { + // กรณีเดิม: ถ้ากดซ้ำตัวเดิม -> ให้ยกเลิกการติดตาม (เคลียร์ Array) + this.subscribeData = []; + } else { + // กรณีใหม่: ถ้ากดตัวใหม่ -> ให้แทนที่ตัวเก่าทันที (มีแค่ตัวเดียวเสมอ) + this.subscribeData = [item]; + } + } + + // Helper Function: เช็คสถานะเพื่อเปลี่ยนสีปุ่ม + isSubscribed(item: any): boolean { + return this.subscribeData.some(sub => sub.prjseq === item.prjseq); + } navigate(path: string) { this.router.navigate([path]); } 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 ce56099..1bec9d2 100644 --- a/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html +++ b/ng-ttc-frontend/src/app/component/sidebar/sidebar.component.html @@ -32,7 +32,7 @@
- Dashboard + หน้าหลัก @@ -48,18 +48,18 @@
- Projects + โครงการของฉัน -
Budgets -
+ -->
- Users + จัดสรรงบประมาณ 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 index 5e40efe..c21a098 100644 --- 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 @@ -1,2 +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 index 62ca4ac..1da391c 100644 --- 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 @@ -62,7 +62,46 @@ export class MainManagerContentComponent implements OnInit { }); } + OnDownloadPrjDoc(value: any): void { + let uri = `/api/ttc/projectdownload`; + let param = { + prjseq: value + } + // isBlob = true + this.generalService.getRequest(uri, param, true).subscribe({ + next: (blob: Blob) => { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `เอกสาร_โครงการ_${value}.zip`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + + const mockResult = { + code: '200', + message: 'Download Successful', + message_th: 'ดาวน์โหลดเอกสารสำเร็จเรียบร้อย' + }; + // this.generalService.trowApi(mockResult); + }, + error: (error: any) => { + if (error.status === 404) { + // แจ้งเตือนเฉพาะเจาะจง + this.generalService.trowApi({ + code: '404', + message: 'No documents found', + message_th: 'ไม่พบเอกสารแนบของโครงการนี้' + }); + } else { + // Error อื่นๆ (500, etc.) + this.generalService.trowApi(error); + } + } + }); + } // OnSetupDashboard(value: any, setupFirst: boolean): void { // const uri = '/api/web/accountingSetup'; diff --git a/ng-ttc-frontend/src/app/interfaces/main.interface.ts b/ng-ttc-frontend/src/app/interfaces/main.interface.ts index 2abcae3..5390030 100644 --- a/ng-ttc-frontend/src/app/interfaces/main.interface.ts +++ b/ng-ttc-frontend/src/app/interfaces/main.interface.ts @@ -8,6 +8,7 @@ export interface IPrjMst { prjacpbdg?: number; prjcomstt?: string; prjacpdtm?: string; + trnacpdtm?: number; } export interface ITrnmst { diff --git a/ng-ttc-frontend/src/app/pipe/dtmtodatetime.pipe.ts b/ng-ttc-frontend/src/app/pipe/dtmtodatetime.pipe.ts index 66863ff..6ccaa8c 100644 --- a/ng-ttc-frontend/src/app/pipe/dtmtodatetime.pipe.ts +++ b/ng-ttc-frontend/src/app/pipe/dtmtodatetime.pipe.ts @@ -12,9 +12,9 @@ export class AccDateFormatPipe implements PipeTransform { const str = value.toString(); if (str.length !== 12) return str; - const dd = str.slice(0, 2); - const mm = str.slice(2, 4); - const yyyy = str.slice(4, 8); + const dd = str.slice(6, 8); + const mm = str.slice(4, 6); + const yyyy = str.slice(0, 4); const hh = str.slice(8, 10); const min = str.slice(10, 12); diff --git a/ng-ttc-frontend/src/app/services/generalservice.ts b/ng-ttc-frontend/src/app/services/generalservice.ts index ee6ac04..ea4fb13 100644 --- a/ng-ttc-frontend/src/app/services/generalservice.ts +++ b/ng-ttc-frontend/src/app/services/generalservice.ts @@ -1,6 +1,6 @@ import { ToastrService } from 'ngx-toastr'; import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; import { environment } from '../../environments/environment'; @@ -18,15 +18,13 @@ export class GeneralService { private toastr: ToastrService ) {} - // ✅ แก้ไข 1: รับ parameter เพื่อกำหนดว่าต้องใส่ Content-Type: application/json หรือไม่ - private getHttpOptions(isJson: boolean = true) { + private getHttpOptions(isJson: boolean = true) { const token = localStorage.getItem('access_token'); let headersConfig: any = { ...(token ? { 'Authorization': `Bearer ${token}` } : {}) }; - // ถ้าเป็น JSON ให้ใส่ Header แต่ถ้าเป็น FormData ห้ามใส่ (Browser จะจัดการเอง) if (isJson) { headersConfig['Content-Type'] = 'application/json'; } @@ -35,6 +33,7 @@ export class GeneralService { return { headers }; } + // Helper: wrap body ให้มี request ครอบเสมอ (ใช้เฉพาะ JSON) private wrapRequestBody(body: any): any { if (body && body.request) { @@ -101,14 +100,38 @@ export class GeneralService { // }); // } - // GET Request (เหมือนเดิม) - getRequest(uri: string): Observable { + getRequest(uri: string, params?: any, isBlob: boolean = false): Observable { const fullUrl = `${this.baseUrl}${uri}`; - return this.http.get(fullUrl, this.getHttpOptions(true)).pipe( // default true + + // 1. แปลง Object เป็น HttpParams + let httpParams = new HttpParams(); + if (params) { + Object.keys(params).forEach(key => { + if (params[key] !== null && params[key] !== undefined) { + httpParams = httpParams.set(key, params[key]); + } + }); + } + + // 2. รวม Headers และ Config + const options: any = { + ...this.getHttpOptions(true), + params: httpParams, + responseType: isBlob ? 'blob' : 'json' // ✅ สลับ Type ตามค่า isBlob + }; + + return this.http.get(fullUrl, options).pipe( map((res: any) => res), catchError((error: any) => { + console.error(`❌ [${isBlob ? 'Download' : 'GET'} Request Error]:`, error); + + // กรณี Download (Blob) ให้ส่ง Error เดิมกลับไปเลย (เพื่อให้ Component ไป parse Blob เป็น JSON Error เอง) + if (isBlob) { + return throwError(() => error); + } + + // กรณี JSON ปกติ แปลง Error ตาม Pattern const response = error?.error; - console.error('❌ [GET Request Error]:', error); return throwError(() => ({ status: error.status, code: response?.code ?? '500', @@ -169,7 +192,7 @@ export class GeneralService { 'ngx-toastr success-toast bg-white bg-opacity-90 text-green-700 shadow-lg' }); } else { - this.toastr.error(`${msgTh || msg}`,'error',{ + this.toastr.error(`${msgTh || msg}`,`${msg}`,{ positionClass: 'toast-top-right', timeOut: 3500, progressBar: true,