@kengcom202/kcore-ui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kengcom202/kcore-ui",
3
- "version": "0.2.0",
4
- "description": "Angular UI กลาง: ช่องเลือกวันที่แบบ พ.ศ. และช่องเลือกเวลาแบบหน้าปัด และ dropdown ค้นหาได้ (ไม่พึ่งไลบรารีภายนอก)",
3
+ "version": "0.4.0",
4
+ "description": "Angular UI กลาง: ช่องเลือกวันที่แบบ พ.ศ., ช่องเลือกเวลาแบบหน้าปัด, dropdown ค้นหาได้, ตัวแก้ข้อความไทยที่คัดลอกจาก PDF และชุดหน้าเข้าสู่ระบบ/ลงทะเบียน/ข้อมูลส่วนตัว/config (ไม่พึ่งไลบรารีภายนอก)",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
7
7
  "type": "git",
@@ -12,8 +12,11 @@
12
12
  "access": "public"
13
13
  },
14
14
  "peerDependencies": {
15
+ "@angular/common": "^22.0.0",
15
16
  "@angular/core": "^22.0.0",
16
- "@angular/forms": "^22.0.0"
17
+ "@angular/forms": "^22.0.0",
18
+ "@angular/router": "^22.0.0",
19
+ "rxjs": "^7.4.0"
17
20
  },
18
21
  "dependencies": {
19
22
  "tslib": "^2.3.0"
@@ -1,6 +1,8 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ApplicationRef, ElementRef, EnvironmentInjector, NgZone, OnDestroy, Type } from "@angular/core";
2
+ import { AfterContentInit, ApplicationRef, ElementRef, EnvironmentInjector, EnvironmentProviders, InjectionToken, NgZone, OnDestroy, OnInit, Type } from "@angular/core";
3
3
  import { ControlValueAccessor } from "@angular/forms";
4
+ import { HttpInterceptorFn } from "@angular/common/http";
5
+ import { CanActivateFn, Routes } from "@angular/router";
4
6
  /**
5
7
  * ช่องเลือกวันที่แบบไทย ใช้กับ <input type="text" appDatePicker formControlName="...">
6
8
  * - ค่าใน form control เป็น ค.ศ. yyyy-MM-dd เสมอ (ตรงกับที่ API ใช้) ส่วนในช่องแสดงเป็น พ.ศ.
@@ -304,4 +306,518 @@ export declare class AnchoredPopup<T> {
304
306
  open(setup: (instance: T) => void): void;
305
307
  close(): void;
306
308
  position(): void;
309
+ }
310
+ /**
311
+ * แก้ข้อความไทยที่คัดลอกมาจาก PDF: แปลงรหัส PUA (□) กลับเป็นสระ/วรรณยุกต์,
312
+ * ลบช่องว่างที่แทรกหน้าสระบน/ล่าง/วรรณยุกต์ ("เชื ่อม") และรวม "ํา" (นิคหิต + สระอา) เป็น "ำ"
313
+ * ข้อความที่ไม่มีปัญหาคืนตามเดิม
314
+ */
315
+ export declare function fixThaiText(text: string): string;
316
+ /**
317
+ * แก้ข้อความไทยจาก PDF ตอนวาง (paste) ลงทุกช่อง input / textarea ของแอป — ใส่ใน app.config.ts ครั้งเดียว
318
+ *
319
+ * ```ts
320
+ * providers: [provideThaiPasteFix()]
321
+ * ```
322
+ *
323
+ * ถ้าข้อความไม่ต้องแก้จะปล่อยให้วางตามปกติ ถ้าต้องแก้จะวางข้อความที่แก้แล้วแทน
324
+ * ผ่าน execCommand('insertText') เพื่อให้ ngModel / formControl ได้ event input และ Ctrl+Z ย้อนได้
325
+ */
326
+ export declare function provideThaiPasteFix(): EnvironmentProviders;
327
+ /** ค่าที่โปรเจกต์ส่งให้ provideKcAuth() — ทุกค่ายกเว้น appName มีค่าเริ่มต้น */
328
+ export interface KcAuthOptions {
329
+ /** ชื่อระบบ แสดงบนหน้าเข้าสู่ระบบ/ลงทะเบียน */
330
+ appName: string;
331
+ /** โลโก้บนหน้าเข้าสู่ระบบ/ลงทะเบียน เช่น 'images/logo.png' (ไม่ใส่ = ไม่แสดง) */
332
+ logoUrl?: string;
333
+ /** ต้นทางของ API ค่าเริ่มต้น '/api' — token แนบเฉพาะคำขอที่ขึ้นต้นด้วยค่านี้ */
334
+ apiBase?: string;
335
+ /** หน้าที่พาไปหลังเข้าสู่ระบบ (ถ้าไม่มี returnUrl) และหน้าที่ผู้ไม่ใช่ผู้ดูแลถูกพาไปจากหน้า config ค่าเริ่มต้น '/' */
336
+ homeUrl?: string;
337
+ /** เปิดปุ่ม SSO (OIDC เช่น Keycloak) — label คือชื่อที่แสดงบนปุ่ม ค่าเริ่มต้น 'SSO'; false/ไม่ใส่ = ปิด */
338
+ sso?: false | {
339
+ label?: string;
340
+ };
341
+ /**
342
+ * เข้าสู่ระบบด้วยชื่อผู้ใช้/รหัสผ่าน ค่าเริ่มต้น true — false = หน้าเข้าสู่ระบบมีแต่ปุ่ม SSO ตรงกลาง
343
+ * (มีผลเฉพาะเมื่อเปิด sso ไว้ ถ้าปิดทั้งคู่จะยังแสดงช่องรหัสผ่าน กันไม่ให้ไม่มีทางเข้าระบบ)
344
+ */
345
+ passwordLogin?: boolean;
346
+ /**
347
+ * การลงทะเบียนผู้ใช้ใหม่
348
+ * 'none' — ไม่เปิดให้สมัครเอง (ผู้ดูแลเพิ่มให้) — ค่าเริ่มต้น
349
+ * 'form' — กรอกฟอร์มเองที่ /register
350
+ * 'sso' — ยืนยันตัวตนผ่าน SSO ก่อน แล้ว API ส่งตั๋วลงทะเบียนมาให้กรอกต่อที่ /register
351
+ */
352
+ register?: 'none' | 'form' | 'sso';
353
+ /** ชื่อเรียกหน่วยงานที่สังกัด เช่น 'หน่วยงาน', 'โรงพยาบาล', 'แผนก' ค่าเริ่มต้น 'หน่วยงาน' */
354
+ orgLabel?: string;
355
+ /** ค่า role ที่ถือว่าเป็นผู้ดูแล (เข้า kcAdminGuard ได้) ค่าเริ่มต้น ['admin'] */
356
+ adminRoles?: string[];
357
+ /** ความยาวรหัสผ่านขั้นต่ำ ค่าเริ่มต้น 4 */
358
+ passwordMinLength?: number;
359
+ /** คำอธิบายคอลัมน์ของแต่ละกลุ่มในหน้า kcllu เช่น { hospital: 'k_code = รหัสหน่วยงาน, k_name = ชื่อหน่วยงาน' } */
360
+ kclluHints?: Record<string, string>;
361
+ }
362
+ /** ค่าที่ใช้จริงหลังเติมค่าเริ่มต้น */
363
+ export interface KcAuthConfig {
364
+ appName: string;
365
+ logoUrl: string;
366
+ apiBase: string;
367
+ homeUrl: string;
368
+ sso: {
369
+ label: string;
370
+ } | null;
371
+ passwordLogin: boolean;
372
+ register: 'none' | 'form' | 'sso';
373
+ orgLabel: string;
374
+ adminRoles: string[];
375
+ passwordMinLength: number;
376
+ kclluHints: Record<string, string>;
377
+ }
378
+ export declare const KC_AUTH_CONFIG: InjectionToken<KcAuthConfig>;
379
+ /** path ของหน้าที่ไม่ต้องเข้าสู่ระบบ — kcAuthRoutes() สร้าง route ตามนี้ (ห้ามเปลี่ยน = major) */
380
+ export declare const KC_AUTH_PATHS: {
381
+ readonly login: "/login";
382
+ readonly register: "/register";
383
+ readonly ssoCallback: "/sso-callback";
384
+ };
385
+ export declare function resolveKcAuthConfig(o: KcAuthOptions): KcAuthConfig;
386
+ /**
387
+ * ตั้งค่าชุดหน้าบัญชีผู้ใช้ — ใส่ใน app.config.ts ครั้งเดียว คู่กับ kcAuthInterceptor
388
+ * providers: [
389
+ * provideHttpClient(withInterceptors([kcAuthInterceptor])),
390
+ * provideKcAuth({ appName: 'ระบบ...', sso: { label: 'DMS SSO' }, register: 'sso' }),
391
+ * ]
392
+ */
393
+ export declare function provideKcAuth(options: KcAuthOptions): EnvironmentProviders;
394
+ /** ผู้ใช้ที่เข้าสู่ระบบอยู่ (เก็บใน localStorage คู่กับ token) */
395
+ export interface KcUser {
396
+ id: string;
397
+ username: string;
398
+ fullName: string;
399
+ role: string;
400
+ org: string;
401
+ orgName: string;
402
+ }
403
+ /** POST {api}/user/login → KcSession */
404
+ export interface KcSession {
405
+ token: string;
406
+ user: KcUser;
407
+ }
408
+ /** GET {api}/user/sso/authorize-url */
409
+ export interface KcSsoAuthorize {
410
+ url: string;
411
+ state: string;
412
+ }
413
+ /** POST {api}/user/sso/callback { code } */
414
+ export type KcSsoCallbackResult = ({
415
+ mode: 'signed-in';
416
+ } & KcSession) | {
417
+ mode: 'register';
418
+ ticket: string;
419
+ };
420
+ /** GET {api}/user/register-info[?ticket=] — ตั๋วจาก SSO ทำให้ได้ชื่อ-สกุล (และหน่วยงาน) ที่ยืนยันแล้ว */
421
+ export interface KcRegisterInfo {
422
+ /** ชื่อ-สกุลจาก SSO — มีค่า = ช่องชื่อแก้ไม่ได้ */
423
+ fullName?: string;
424
+ /** เลขบัตรประชาชนจาก SSO — มีค่า = แสดงแบบอ่านอย่างเดียว */
425
+ cid?: string;
426
+ /** ข้อความแจ้งเหนือฟอร์ม เช่น "พบข้อมูลบุคลากรของท่านในระบบแล้ว แต่ยังไม่มีบัญชีผู้ใช้..." */
427
+ notice?: string;
428
+ org?: string;
429
+ /** true = หน่วยงานถูกกำหนดแล้ว (เช่นมีข้อมูลบุคคลเดิม) แก้ไม่ได้ */
430
+ orgLocked?: boolean;
431
+ /** หน่วยงานที่เลือกได้ — ว่าง = ระบบนี้ไม่ใช้หน่วยงาน (ซ่อนช่อง) */
432
+ orgs: SearchOption[];
433
+ }
434
+ /** POST {api}/user/register */
435
+ export interface KcRegisterRequest {
436
+ ticket?: string;
437
+ fullName: string;
438
+ username: string;
439
+ password: string;
440
+ org: string;
441
+ }
442
+ /** มี token + user = เข้าใช้งานได้ทันที, ไม่มี = แสดง message (เช่น รอผู้ดูแลอนุมัติ) */
443
+ export interface KcRegisterResult {
444
+ message?: string;
445
+ token?: string;
446
+ user?: KcUser;
447
+ }
448
+ /** GET {api}/user/me */
449
+ export interface KcProfile {
450
+ username: string;
451
+ fullName: string;
452
+ org: string;
453
+ orgName: string;
454
+ email: string;
455
+ mobile: string;
456
+ }
457
+ /** PUT {api}/user/me — password ว่าง = ไม่เปลี่ยน */
458
+ export interface KcProfileUpdate {
459
+ username: string;
460
+ email: string;
461
+ mobile: string;
462
+ password: string;
463
+ }
464
+ /** แถวในหน้า config ผู้ใช้ */
465
+ export interface KcConfigUser {
466
+ id: string;
467
+ username: string;
468
+ fullName: string;
469
+ role: string;
470
+ active: boolean;
471
+ org: string;
472
+ orgName: string;
473
+ email: string;
474
+ mobile: string;
475
+ /** ข้อความที่ API จัดรูปแบบแล้ว (แสดงตรง ๆ) หรือ null */
476
+ lastLogin: string | null;
477
+ }
478
+ /** GET {api}/config/users */
479
+ export interface KcConfigUsersResponse {
480
+ users: KcConfigUser[];
481
+ orgs: SearchOption[];
482
+ roles: SearchOption[];
483
+ }
484
+ /** PUT {api}/config/users/{id} — password ว่าง = ไม่เปลี่ยน */
485
+ export interface KcConfigUserUpdate {
486
+ username: string;
487
+ password: string;
488
+ role: string;
489
+ active: boolean;
490
+ org: string;
491
+ }
492
+ /** GET {api}/config/kcllu/titles */
493
+ export interface KclluTitle {
494
+ title: string;
495
+ count: number;
496
+ /** true = ดูได้อย่างเดียว (เช่นกลุ่ม menu) */
497
+ readOnly: boolean;
498
+ }
499
+ /** GET {api}/config/kcllu?title= — POST {api}/config/kcllu และ PUT {api}/config/kcllu/{id} ส่งรูปเดียวกัน (+ title) */
500
+ export interface KclluRow {
501
+ /** k_ser — 0 = แถวใหม่ */
502
+ id: number;
503
+ code: string;
504
+ name: string;
505
+ name1: string;
506
+ value: string;
507
+ grp: string;
508
+ /** k_no เป็นข้อความตัวเลข ('' = ไม่ระบุ) */
509
+ no: string;
510
+ mark: string;
511
+ active: boolean;
512
+ }
513
+ /** คำตอบของ endpoint ที่บันทึกข้อมูล */
514
+ export interface KcMessage {
515
+ message?: string;
516
+ }
517
+ /** ข้อความจาก API ({ message }) หรือข้อความสำรอง */
518
+ export declare function kcErrorMessage(err: unknown, fallback: string): string;
519
+ export declare const KC_SSO_STATE_KEY = "kc_sso_state";
520
+ export declare const KC_SSO_TICKET_KEY = "kc_sso_ticket";
521
+ export declare const KC_RETURN_URL_KEY = "kc_return_url";
522
+ /** token เป็น JWT ที่มี exp และเลยเวลาแล้ว — token รูปแบบอื่นถือว่ายังไม่หมดอายุ (ให้ API ตัดสินด้วย 401) */
523
+ export declare function kcTokenExpired(token: string, now?: number): boolean;
524
+ /**
525
+ * session ของผู้ใช้ที่เข้าสู่ระบบ — เก็บ { token, user } ใน localStorage คีย์ kc_session
526
+ * แท็บอื่นเข้า/ออกจากระบบ แท็บนี้รู้ด้วย (event storage)
527
+ */
528
+ export declare class KcAuthService {
529
+ private readonly config;
530
+ private readonly router;
531
+ private readonly win;
532
+ private readonly state;
533
+ readonly session: import("@angular/core").Signal<KcSession | null>;
534
+ readonly user: import("@angular/core").Signal<KcUser | null>;
535
+ readonly isAdmin: import("@angular/core").Signal<boolean>;
536
+ constructor();
537
+ /** มี session และ token ยังไม่หมดอายุ */
538
+ isLoggedIn(): boolean;
539
+ token(): string;
540
+ /** เริ่ม session ใหม่ (ล้างของผู้ใช้คนก่อนทั้งหมด) */
541
+ start(session: KcSession): void;
542
+ /** แก้ข้อมูลผู้ใช้ใน session เช่น หลังเปลี่ยนชื่อผู้ใช้ที่หน้าข้อมูลส่วนตัว */
543
+ updateUser(patch: Partial<KcUser>): void;
544
+ /** ล้าง session โดยไม่เปลี่ยนหน้า */
545
+ clear(): void;
546
+ /** ออกจากระบบแล้วไปหน้าเข้าสู่ระบบ */
547
+ logout(): Promise<boolean>;
548
+ /** url ที่ปลอดภัยสำหรับพากลับหลังเข้าสู่ระบบ — ต้องเป็น path ภายในแอป ไม่ใช่หน้า login/register */
549
+ safeReturnUrl(url: string | null | undefined): string;
550
+ setTemp(key: string, value: string): void;
551
+ getTemp(key: string): string;
552
+ /** อ่านแล้วลบทิ้ง */
553
+ takeTemp(key: string): string;
554
+ /** เปลี่ยนหน้าไป url ภายนอก (หน้า SSO) */
555
+ redirect(url: string): void;
556
+ private read;
557
+ private storage;
558
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcAuthService, never>;
559
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
560
+ }
561
+ /** หน้าที่ต้องเข้าสู่ระบบก่อน — ไม่ได้เข้า = ไป /login?returnUrl=... */
562
+ export declare const kcAuthGuard: CanActivateFn;
563
+ /** หน้าเฉพาะผู้ดูแล (role อยู่ใน adminRoles) — ผู้ใช้ทั่วไปถูกพาไป homeUrl (API ต้องตรวจสิทธิ์ซ้ำเสมอ) */
564
+ export declare const kcAdminGuard: CanActivateFn;
565
+ /**
566
+ * แนบ Authorization: Bearer <token> กับคำขอที่ขึ้นต้นด้วย apiBase และถ้า API ตอบ 401 ให้ล้าง session
567
+ * แล้วกลับไปหน้าเข้าสู่ระบบ — ยกเว้นตอนอยู่หน้า login / register / sso-callback ที่ให้หน้านั้นแสดงข้อความเอง
568
+ * (เช่นรหัสผ่านผิด หรือตั๋วลงทะเบียนหมดอายุ)
569
+ */
570
+ export declare const kcAuthInterceptor: HttpInterceptorFn;
571
+ /**
572
+ * route ของหน้าที่ไม่ต้องเข้าสู่ระบบ (อยู่นอก layout ของโปรเจกต์) — ใส่ไว้บนสุดของ routes
573
+ * export const routes: Routes = [
574
+ * ...kcAuthRoutes(),
575
+ * { path: '', component: MainLayoutComponent, children: [
576
+ * { path: 'user/detail', component: KcProfileComponent, canActivate: [kcAuthGuard] },
577
+ * { path: 'config/users', component: KcConfigUsersComponent, canActivate: [kcAdminGuard] },
578
+ * { path: 'config/kcllu', component: KcConfigKclluComponent, canActivate: [kcAdminGuard] },
579
+ * ] },
580
+ * ];
581
+ * path ตรงกับ KC_AUTH_PATHS (login, register, sso-callback)
582
+ */
583
+ export declare function kcAuthRoutes(): Routes;
584
+ /**
585
+ * ครอบช่องรหัสผ่านเพื่อเพิ่มปุ่มรูปดวงตาท้ายช่อง กดสลับดู/ซ่อนรหัสที่พิมพ์
586
+ * <kc-password><input class="kc-auth-input" type="password" formControlName="password" /></kc-password>
587
+ * ไม่ยุ่งกับค่าในฟอร์ม (ใช้ได้ทั้ง formControlName / ngModel) — แค่สลับ type ของ <input> ข้างใน
588
+ */
589
+ export declare class KcPasswordToggleComponent implements AfterContentInit {
590
+ private readonly host;
591
+ protected readonly shown: import("@angular/core").WritableSignal<boolean>;
592
+ private input;
593
+ constructor();
594
+ ngAfterContentInit(): void;
595
+ protected toggle(): void;
596
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcPasswordToggleComponent, never>;
597
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcPasswordToggleComponent, "kc-password", never, {}, {}, never, ["*"], true, never>;
598
+ }
599
+ /**
600
+ * หน้าเข้าสู่ระบบ (route /login จาก kcAuthRoutes())
601
+ * ชื่อผู้ใช้/รหัสผ่าน → POST {api}/user/login → KcSession
602
+ * ปุ่ม SSO (ถ้าเปิด) → GET {api}/user/sso/authorize-url → ไปหน้า SSO แล้วกลับมาที่ /sso-callback
603
+ * query: returnUrl = หน้าที่จะกลับไปหลังเข้าสู่ระบบ, expired=1 = แจ้งหมดเวลาการใช้งาน
604
+ * เนื้อหาที่ใส่ไว้ใน <kc-login>...</kc-login> แสดงท้ายการ์ด (เช่นเบอร์ติดต่อผู้ดูแล)
605
+ */
606
+ export declare class KcLoginComponent implements OnInit {
607
+ protected readonly config: import("@kengcom202/kcore-ui").KcAuthConfig;
608
+ protected readonly paths: {
609
+ readonly login: "/login";
610
+ readonly register: "/register";
611
+ readonly ssoCallback: "/sso-callback";
612
+ };
613
+ private readonly auth;
614
+ private readonly http;
615
+ private readonly router;
616
+ private readonly route;
617
+ protected readonly busy: import("@angular/core").WritableSignal<"" | "sso" | "password">;
618
+ protected readonly message: import("@angular/core").WritableSignal<{
619
+ text: string;
620
+ error: boolean;
621
+ } | null>;
622
+ protected readonly form: import("@angular/forms").FormGroup<{
623
+ username: import("@angular/forms").FormControl<string>;
624
+ password: import("@angular/forms").FormControl<string>;
625
+ }>;
626
+ constructor();
627
+ private get returnUrl();
628
+ ngOnInit(): void;
629
+ protected submit(): void;
630
+ protected startSso(): void;
631
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcLoginComponent, never>;
632
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcLoginComponent, "kc-login", never, {}, {}, never, ["*"], true, never>;
633
+ }
634
+ /**
635
+ * หน้าลงทะเบียนผู้ใช้ใหม่ (route /register) — รูปแบบตาม ictprocure: กล่องเดียว ช่องเรียงแถวเดียว
636
+ * ทำงานตาม register ใน provideKcAuth()
637
+ * 'sso' — ต้องมาจาก /sso-callback พร้อมตั๋ว ชื่อ-สกุล / เลขบัตรประชาชน (และหน่วยงานถ้า orgLocked) มาจาก API แก้ไม่ได้
638
+ * 'form' — กรอกชื่อ-สกุลเอง
639
+ * 'none' — แจ้งว่าไม่เปิดให้ลงทะเบียน
640
+ * อีเมล / มือถือไม่ถามตอนลงทะเบียน — ผู้ใช้กรอกต่อที่หน้าบัญชีของฉัน
641
+ * GET {api}/user/register-info[?ticket=] → KcRegisterInfo, POST {api}/user/register ← KcRegisterRequest
642
+ */
643
+ export declare class KcRegisterComponent implements OnInit {
644
+ protected readonly config: import("@kengcom202/kcore-ui").KcAuthConfig;
645
+ protected readonly paths: {
646
+ readonly login: "/login";
647
+ readonly register: "/register";
648
+ readonly ssoCallback: "/sso-callback";
649
+ };
650
+ protected readonly ssoLabel: string;
651
+ private readonly auth;
652
+ private readonly http;
653
+ private readonly router;
654
+ protected readonly loading: import("@angular/core").WritableSignal<boolean>;
655
+ /** พร้อมให้กรอก (โหลดข้อมูลสำเร็จ และโหมดเปิดให้ลงทะเบียน) */
656
+ protected readonly ready: import("@angular/core").WritableSignal<boolean>;
657
+ protected readonly saving: import("@angular/core").WritableSignal<boolean>;
658
+ protected readonly error: import("@angular/core").WritableSignal<string>;
659
+ /** ข้อความหลังลงทะเบียนสำเร็จ — มีค่า = ซ่อนฟอร์มกันกดส่งซ้ำ */
660
+ protected readonly done: import("@angular/core").WritableSignal<string>;
661
+ protected readonly notice: import("@angular/core").WritableSignal<string>;
662
+ protected readonly fromSso: import("@angular/core").WritableSignal<boolean>;
663
+ protected readonly cid: import("@angular/core").WritableSignal<string>;
664
+ protected readonly orgs: import("@angular/core").WritableSignal<SearchOption[]>;
665
+ protected readonly orgLocked: import("@angular/core").WritableSignal<boolean>;
666
+ private readonly lockedOrg;
667
+ protected readonly orgName: import("@angular/core").Signal<string>;
668
+ protected readonly form: import("@angular/forms").FormGroup<{
669
+ fullName: import("@angular/forms").FormControl<string>;
670
+ org: import("@angular/forms").FormControl<string>;
671
+ username: import("@angular/forms").FormControl<string>;
672
+ password: import("@angular/forms").FormControl<string>;
673
+ confirmPassword: import("@angular/forms").FormControl<string>;
674
+ }>;
675
+ protected ticket: string;
676
+ constructor();
677
+ ngOnInit(): void;
678
+ protected submit(): void;
679
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcRegisterComponent, never>;
680
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcRegisterComponent, "kc-register", never, {}, {}, never, never, true, never>;
681
+ }
682
+ /**
683
+ * หน้ารับ redirect กลับจาก SSO (route /sso-callback) — path นี้ต้องตรงกับ redirect_uri ที่ API ส่งให้ SSO
684
+ * และที่ลงทะเบียนไว้กับ SSO server
685
+ * ?code=&state= → ตรวจ state → POST {api}/user/sso/callback { code }
686
+ * signed-in → เริ่ม session แล้วกลับหน้าเดิม / homeUrl
687
+ * register → เก็บตั๋วไว้ใน sessionStorage แล้วไป /register
688
+ * ไม่มี code (เช่นเปิดจากเมนูของ SSO portal) → เริ่ม flow ใหม่เอง
689
+ */
690
+ export declare class KcSsoCallbackComponent implements OnInit {
691
+ private readonly config;
692
+ private readonly auth;
693
+ private readonly http;
694
+ private readonly route;
695
+ private readonly router;
696
+ protected readonly paths: {
697
+ readonly login: "/login";
698
+ readonly register: "/register";
699
+ readonly ssoCallback: "/sso-callback";
700
+ };
701
+ protected readonly label: string;
702
+ protected readonly message: import("@angular/core").WritableSignal<string>;
703
+ protected readonly failed: import("@angular/core").WritableSignal<boolean>;
704
+ constructor();
705
+ ngOnInit(): void;
706
+ private fail;
707
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcSsoCallbackComponent, never>;
708
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcSsoCallbackComponent, "kc-sso-callback", never, {}, {}, never, never, true, never>;
709
+ }
710
+ /**
711
+ * หน้า "บัญชีของฉัน" (user/detail) — รูปแบบตาม ictprocure: กล่องเดียวกลางหน้า ช่องเรียงแถวเดียว
712
+ * วางใน layout ของโปรเจกต์พร้อม canActivate: [kcAuthGuard]
713
+ * ชื่อ-สกุลและหน่วยงานแสดงอย่างเดียว (หน่วยงานกำหนดสิทธิ์การเห็นข้อมูล ย้ายได้โดยผู้ดูแลที่หน้า config)
714
+ * แก้ได้: อีเมล มือถือ ชื่อผู้ใช้ รหัสผ่าน — เปลี่ยนรหัสผ่านไม่ต้องกรอกรหัสเดิม เว้นว่าง = ไม่เปลี่ยน
715
+ * GET {api}/user/me → KcProfile, PUT {api}/user/me ← KcProfileUpdate
716
+ */
717
+ export declare class KcProfileComponent implements OnInit {
718
+ protected readonly config: import("@kengcom202/kcore-ui").KcAuthConfig;
719
+ private readonly auth;
720
+ private readonly http;
721
+ protected readonly loading: import("@angular/core").WritableSignal<boolean>;
722
+ /** โหลดข้อมูลไม่สำเร็จ — ไม่แสดงฟอร์ม (กันบันทึกค่าว่างทับของเดิม) */
723
+ protected readonly loadFailed: import("@angular/core").WritableSignal<boolean>;
724
+ protected readonly saving: import("@angular/core").WritableSignal<boolean>;
725
+ protected readonly error: import("@angular/core").WritableSignal<string>;
726
+ protected readonly success: import("@angular/core").WritableSignal<string>;
727
+ protected readonly fullName: import("@angular/core").WritableSignal<string>;
728
+ protected readonly orgName: import("@angular/core").WritableSignal<string>;
729
+ protected readonly form: import("@angular/forms").FormGroup<{
730
+ email: import("@angular/forms").FormControl<string>;
731
+ mobile: import("@angular/forms").FormControl<string>;
732
+ username: import("@angular/forms").FormControl<string>;
733
+ password: import("@angular/forms").FormControl<string>;
734
+ confirmPassword: import("@angular/forms").FormControl<string>;
735
+ }>;
736
+ constructor();
737
+ ngOnInit(): void;
738
+ /** ช่องนี้ผิดและผู้ใช้แตะแล้ว — แสดงข้อความใต้ช่อง */
739
+ protected bad(name: 'email' | 'mobile' | 'username'): boolean;
740
+ protected submit(): void;
741
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcProfileComponent, never>;
742
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcProfileComponent, "kc-profile", never, {}, {}, never, never, true, never>;
743
+ }
744
+ interface UserEdit extends KcConfigUserUpdate {
745
+ id: string;
746
+ fullName: string;
747
+ confirmPassword: string;
748
+ }
749
+ /**
750
+ * หน้า config › ผู้ใช้งานระบบ (เฉพาะผู้ดูแล) — วางใน layout ของโปรเจกต์พร้อม canActivate: [kcAdminGuard]
751
+ * ค้นหา แล้วคลิกแถวเพื่อแก้ ชื่อผู้ใช้ / ระดับผู้ใช้ / สถานะ / หน่วยงาน / ตั้งรหัสผ่านใหม่
752
+ * ไม่มีการลบ — ใช้ "ระงับการใช้งาน" แทน และแก้ระดับ/สถานะของตัวเองไม่ได้ (กันผู้ดูแลล็อกตัวเองออก)
753
+ * GET {api}/config/users → { users, orgs, roles }, PUT {api}/config/users/{id} ← KcConfigUserUpdate
754
+ */
755
+ export declare class KcConfigUsersComponent implements OnInit {
756
+ protected readonly config: import("@kengcom202/kcore-ui").KcAuthConfig;
757
+ private readonly auth;
758
+ private readonly http;
759
+ protected readonly users: import("@angular/core").WritableSignal<KcConfigUser[]>;
760
+ protected readonly orgs: import("@angular/core").WritableSignal<SearchOption[]>;
761
+ protected readonly roles: import("@angular/core").WritableSignal<SearchOption[]>;
762
+ protected readonly loading: import("@angular/core").WritableSignal<boolean>;
763
+ protected readonly saving: import("@angular/core").WritableSignal<boolean>;
764
+ protected readonly error: import("@angular/core").WritableSignal<string>;
765
+ protected readonly success: import("@angular/core").WritableSignal<string>;
766
+ protected readonly editError: import("@angular/core").WritableSignal<string>;
767
+ protected readonly search: import("@angular/core").WritableSignal<string>;
768
+ protected readonly editing: import("@angular/core").WritableSignal<UserEdit | null>;
769
+ protected readonly myId: import("@angular/core").Signal<string>;
770
+ /** ตัวเลือกหน่วยงานในป็อปอัป — มี "ไม่ระบุ" ไว้ล้างค่า */
771
+ protected readonly orgOptions: import("@angular/core").Signal<SearchOption[]>;
772
+ protected readonly filtered: import("@angular/core").Signal<KcConfigUser[]>;
773
+ constructor();
774
+ ngOnInit(): void;
775
+ protected load(): void;
776
+ protected roleName(role: string): string;
777
+ protected hasRole(role: string): boolean;
778
+ protected edit(u: KcConfigUser): void;
779
+ protected close(): void;
780
+ protected save(): void;
781
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcConfigUsersComponent, never>;
782
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcConfigUsersComponent, "kc-config-users", never, {}, {}, never, never, true, never>;
783
+ }
784
+ /**
785
+ * หน้า config › ข้อมูลอ้างอิง (ตาราง kcllu) เฉพาะผู้ดูแล — วางใน layout ของโปรเจกต์พร้อม canActivate: [kcAdminGuard]
786
+ * เลือกกลุ่ม (k_title) แล้วคลิกแถวเพื่อแก้ / ปุ่มเพิ่มข้อมูล — ไม่มีการลบ ใช้ "ปิดใช้งาน" แทน
787
+ * กลุ่มที่ API ตอบ readOnly (เช่น menu) ดูได้อย่างเดียว
788
+ * คำอธิบายคอลัมน์ของแต่ละกลุ่มตั้งที่ provideKcAuth({ kclluHints })
789
+ * GET {api}/config/kcllu/titles → KclluTitle[]
790
+ * GET {api}/config/kcllu?title= → KclluRow[]
791
+ * POST {api}/config/kcllu / PUT {api}/config/kcllu/{id} ← KclluRow + title
792
+ */
793
+ export declare class KcConfigKclluComponent implements OnInit {
794
+ private readonly config;
795
+ private readonly http;
796
+ private readonly api;
797
+ protected readonly titles: import("@angular/core").WritableSignal<KclluTitle[]>;
798
+ protected readonly title: import("@angular/core").WritableSignal<string>;
799
+ protected readonly rows: import("@angular/core").WritableSignal<KclluRow[]>;
800
+ protected readonly loading: import("@angular/core").WritableSignal<boolean>;
801
+ protected readonly saving: import("@angular/core").WritableSignal<boolean>;
802
+ protected readonly showInactive: import("@angular/core").WritableSignal<boolean>;
803
+ protected readonly error: import("@angular/core").WritableSignal<string>;
804
+ protected readonly success: import("@angular/core").WritableSignal<string>;
805
+ protected readonly editError: import("@angular/core").WritableSignal<string>;
806
+ /** แถวที่กำลังแก้ — id 0 = เพิ่มใหม่ */
807
+ protected readonly editing: import("@angular/core").WritableSignal<KclluRow | null>;
808
+ protected readonly titleOptions: import("@angular/core").Signal<SearchOption[]>;
809
+ protected readonly readOnly: import("@angular/core").Signal<boolean>;
810
+ protected readonly hint: import("@angular/core").Signal<string>;
811
+ protected readonly visibleRows: import("@angular/core").Signal<KclluRow[]>;
812
+ constructor();
813
+ ngOnInit(): void;
814
+ private loadTitles;
815
+ protected select(title: string): void;
816
+ private loadRows;
817
+ protected add(): void;
818
+ protected edit(row: KclluRow): void;
819
+ protected close(): void;
820
+ protected save(): void;
821
+ static ɵfac: i0.ɵɵFactoryDeclaration<KcConfigKclluComponent, never>;
822
+ static ɵcmp: i0.ɵɵComponentDeclaration<KcConfigKclluComponent, "kc-config-kcllu", never, {}, {}, never, never, true, never>;
307
823
  }