cloud-ide-core 2.0.6 → 2.0.7

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.
@@ -1,6 +1,6 @@
1
1
  import { authGuard } from 'cloud-ide-auth';
2
2
  import * as i0 from '@angular/core';
3
- import { Injectable, Component, inject, DestroyRef, viewChild, signal, computed, ViewChild, ChangeDetectorRef } from '@angular/core';
3
+ import { Injectable, Component, inject, DestroyRef, viewChild, signal, computed, ChangeDetectorRef, ViewChild } from '@angular/core';
4
4
  import * as i1$1 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
6
6
  import * as i1$2 from '@angular/forms';
@@ -9,11 +9,11 @@ import { Router, ActivatedRoute } from '@angular/router';
9
9
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
10
  import { BehaviorSubject, throwError, Observable, Subject, takeUntil, debounceTime, distinctUntilChanged } from 'rxjs';
11
11
  import { tap, catchError, map } from 'rxjs/operators';
12
- import { coreRoutesUrl, generateStringFromObject, cidePath, hostManagerRoutesUrl, MDesignationInsertUpdatePayload, generateObjectFromString, userRoutesUrl, AuthUserMstGetByIdPayload, customEncrypt, AuthUserMstListPayload } from 'cloud-ide-lms-model';
12
+ import { coreRoutesUrl, generateStringFromObject, cidePath, hostManagerRoutesUrl, MDesignationInsertUpdatePayload, generateObjectFromString, userRoutesUrl, AuthUserMstGetByIdPayload, customEncrypt, customDecrypt, AuthUserMstListPayload } from 'cloud-ide-lms-model';
13
13
  import * as i1 from '@angular/common/http';
14
14
  import { HttpClient } from '@angular/common/http';
15
- import { NotificationService, CideEleDataGridComponent, CideEleButtonComponent, CideInputComponent, CideSelectComponent, CideTextareaComponent, CideIconComponent, CideEleDropdownComponent, ConfirmationService, CideEleGlobalNotificationsComponent, CideEleConfirmationModalComponent, CideEleJsonEditorComponent, CideEleFileManagerService, CideEleFileInputComponent, CideEleTabComponent, CideEleFileImageDirective } from 'cloud-ide-element';
16
- import { AppStateHelperService } from 'cloud-ide-layout';
15
+ import { NotificationService, CideEleDataGridComponent, CideEleButtonComponent, CideInputComponent, CideSelectComponent, CideTextareaComponent, CideIconComponent, CideEleDropdownComponent, ConfirmationService, CideEleGlobalNotificationsComponent, CideEleConfirmationModalComponent, CideEleJsonEditorComponent, CideEleFileInputComponent, CideEleFileImageDirective, CideEleFileManagerService, CideEleTabComponent } from 'cloud-ide-element';
16
+ import { AppStateHelperService, CideLytFloatingUploadService, CideLytFloatingUploadTriggerDirective } from 'cloud-ide-layout';
17
17
 
18
18
  const coreRoutes = [
19
19
  {
@@ -1361,12 +1361,17 @@ class MenuListComponent {
1361
1361
  */
1362
1362
  onRowReorder(data) {
1363
1363
  console.log('🔄 Row reorder event:', data);
1364
+ console.log('🔄 Changed items (newOrder):', data.newOrder.length);
1365
+ console.log('🔄 All items (allOrders):', data.allOrders?.length || 0);
1364
1366
  // Save original order if not already saved
1365
1367
  if (this.originalOrder().length === 0) {
1366
1368
  this.originalOrder.set([...this.menuItems()]);
1367
1369
  }
1370
+ // Use allOrders if available (complete order), otherwise fallback to newOrder (changed items only)
1371
+ const reorderedData = data.allOrders && data.allOrders.length > 0 ? data.allOrders : data.newOrder;
1372
+ console.log('🔄 Using reordered data with', reorderedData.length, 'items');
1368
1373
  // Update the displayed data with new order
1369
- this.menuItems.set(data.newOrder);
1374
+ this.menuItems.set(reorderedData);
1370
1375
  // Mark that order has changed
1371
1376
  this.hasOrderChanged.set(true);
1372
1377
  // Update grid data
@@ -1386,25 +1391,33 @@ class MenuListComponent {
1386
1391
  /**
1387
1392
  * Save menu order using the change sequence API
1388
1393
  * This method is called by the data grid when save-order action is triggered
1394
+ * Handles both single-level and multi-level (hierarchical) menu structures
1389
1395
  */
1390
1396
  saveMenuOrder() {
1391
1397
  console.log('💾 Saving menu order...');
1392
- // Prepare payload for change sequence API with all current menu items
1398
+ // Get all menu items including children (handle both hierarchical and flat structures)
1399
+ const allMenuItems = this.getAllMenuItemsIncludingChildren(this.menuItems());
1400
+ // Update sequence numbers for all items based on their current order
1401
+ const itemsWithUpdatedSequences = allMenuItems.map((item, index) => ({
1402
+ ...item,
1403
+ syme_order_by: index + 1
1404
+ }));
1405
+ // Prepare payload for change sequence API with all menu items (including children)
1393
1406
  const payload = {
1394
- menu_sequences: this.menuItems().map(item => ({
1407
+ menu_sequences: itemsWithUpdatedSequences.map(item => ({
1395
1408
  syme_id: item._id || '',
1396
1409
  syme_order_by: item.syme_order_by || 1
1397
1410
  }))
1398
1411
  };
1399
- console.log('📤 Sending change sequence payload:', payload);
1412
+ console.log('📤 Sending change sequence payload for', itemsWithUpdatedSequences.length, 'items:', payload);
1400
1413
  // Call the change sequence API
1401
1414
  this.menuService.changeMenuSequence(payload)
1402
1415
  .pipe(takeUntilDestroyed(this.destroyRef))
1403
1416
  .subscribe({
1404
1417
  next: (response) => {
1405
1418
  if (response.success) {
1406
- console.log('✅ Menu sequence updated successfully');
1407
- this.notificationService.success('Menu sequence updated successfully');
1419
+ console.log('✅ Menu sequence updated successfully for', itemsWithUpdatedSequences.length, 'items');
1420
+ this.notificationService.success(`Menu sequence updated successfully for ${itemsWithUpdatedSequences.length} items`);
1408
1421
  // Reset change flag first
1409
1422
  this.hasOrderChanged.set(false);
1410
1423
  // Update original order to current state
@@ -1425,6 +1438,50 @@ class MenuListComponent {
1425
1438
  }
1426
1439
  });
1427
1440
  }
1441
+ /**
1442
+ * Get all menu items including children from the current data structure
1443
+ * This handles both hierarchical and flat menu structures
1444
+ */
1445
+ getAllMenuItemsIncludingChildren(menuItems) {
1446
+ const allItems = [];
1447
+ const processedIds = new Set();
1448
+ const collectItems = (items) => {
1449
+ items.forEach(item => {
1450
+ // Avoid duplicates by checking if item is already processed
1451
+ if (item._id && !processedIds.has(item._id)) {
1452
+ allItems.push(item);
1453
+ processedIds.add(item._id);
1454
+ // Check if item has children property (for hierarchical data from data grid)
1455
+ if (item.children && item.children.length > 0) {
1456
+ collectItems(item.children);
1457
+ }
1458
+ }
1459
+ });
1460
+ };
1461
+ // For flat data structure (which is what data grid sends), just return all items
1462
+ // since they're already in the correct order
1463
+ if (this.isFlatDataStructure(menuItems)) {
1464
+ console.log('🔄 Detected flat data structure, returning all items as-is');
1465
+ return menuItems;
1466
+ }
1467
+ // For hierarchical data structure, collect all items recursively
1468
+ collectItems(menuItems);
1469
+ console.log('🔄 Collected', allItems.length, 'menu items including children');
1470
+ console.log('📊 Items structure:', allItems.map(item => ({
1471
+ id: item._id,
1472
+ title: item.syme_title,
1473
+ parent: item.syme_id_syme,
1474
+ hasChildren: item.children ? item.children.length : 0
1475
+ })));
1476
+ return allItems;
1477
+ }
1478
+ /**
1479
+ * Check if the data structure is flat (no children property) or hierarchical
1480
+ */
1481
+ isFlatDataStructure(menuItems) {
1482
+ // If any item has a children property with items, it's hierarchical
1483
+ return !menuItems.some(item => item.children && item.children.length > 0);
1484
+ }
1428
1485
  /**
1429
1486
  * Reset drag order to original state
1430
1487
  */
@@ -1969,7 +2026,9 @@ class MenuListComponent {
1969
2026
  * Load user rights type ID from general master types
1970
2027
  */
1971
2028
  loadUserRightsTypeId() {
1972
- this.generalMasterTypeService.getTypeList({})
2029
+ this.generalMasterTypeService.getTypeList({
2030
+ sygmt_code: "user_rights"
2031
+ })
1973
2032
  .pipe(takeUntilDestroyed(this.destroyRef))
1974
2033
  .subscribe({
1975
2034
  next: (response) => {
@@ -6327,20 +6386,6 @@ class CideCorePageThemeComponent {
6327
6386
  return title.includes(q) || code.includes(q) || desc.includes(q);
6328
6387
  });
6329
6388
  }, ...(ngDevMode ? [{ debugName: "filteredThemes" }] : []));
6330
- // Helper to resolve preview image URL safely
6331
- getPreviewUrl(theme) {
6332
- const id = theme?.sytm_preview_id_fm || '';
6333
- if (!id)
6334
- return '';
6335
- const svcUnknown = this.themeService;
6336
- const hasGetPreviewUrl = (svc) => typeof svc === 'object' && svc !== null &&
6337
- 'getPreviewUrl' in svc &&
6338
- typeof svc['getPreviewUrl'] === 'function';
6339
- if (hasGetPreviewUrl(svcUnknown)) {
6340
- return svcUnknown.getPreviewUrl(id);
6341
- }
6342
- return '';
6343
- }
6344
6389
  // Input handler to avoid $any casts in template
6345
6390
  onGallerySearchInput(event) {
6346
6391
  const target = event.target;
@@ -6844,12 +6889,26 @@ class CideCorePageThemeComponent {
6844
6889
  */
6845
6890
  cancelForm() {
6846
6891
  this.resetForm();
6892
+ this.goBack();
6847
6893
  }
6848
6894
  /**
6849
6895
  * Go back to page list
6850
6896
  */
6851
6897
  goBack() {
6852
- this.router.navigate(['/core/page']);
6898
+ console.log('🔍 [PageThemeComponent] goBack() called');
6899
+ console.log('🔍 [PageThemeComponent] Current route:', this.router.url);
6900
+ // Try to navigate back to the page management route
6901
+ this.router.navigate(['/core/page']).then(success => {
6902
+ console.log('🔍 [PageThemeComponent] Navigation result:', success);
6903
+ if (!success) {
6904
+ console.log('🔍 [PageThemeComponent] Navigation failed, using browser back');
6905
+ window.history.back();
6906
+ }
6907
+ }).catch(error => {
6908
+ console.error('🔍 [PageThemeComponent] Navigation error:', error);
6909
+ // Fallback: try to go back in browser history
6910
+ window.history.back();
6911
+ });
6853
6912
  }
6854
6913
  /**
6855
6914
  * Reset form
@@ -7024,8 +7083,33 @@ class CideCorePageThemeComponent {
7024
7083
  error: () => { this.loading.set(false); }
7025
7084
  });
7026
7085
  }
7086
+ // File upload methods for preview image
7087
+ getPreviewImageUploadData() {
7088
+ return {
7089
+ altText: 'Theme Preview Image',
7090
+ cyfm_name: 'theme-preview-image',
7091
+ cyfm_alt_text: 'Theme Preview Image',
7092
+ cyfm_type: 'image',
7093
+ cyfm_permissions: ['read'],
7094
+ cyfm_tags: ['theme', 'preview', 'image']
7095
+ };
7096
+ }
7097
+ onPreviewImageUploadSuccess(fileId) {
7098
+ console.log('Preview image uploaded successfully:', fileId);
7099
+ // Update the form control with the uploaded file ID
7100
+ this.themeForm.patchValue({
7101
+ sytm_preview_id_fm: fileId
7102
+ });
7103
+ }
7104
+ onPreviewImageUploadError(error) {
7105
+ console.error('Preview image upload error:', error);
7106
+ this.error.set('Failed to upload preview image: ' + error);
7107
+ }
7108
+ onPreviewImageUploadProgress(progress) {
7109
+ console.log('Preview image upload progress:', progress + '%');
7110
+ }
7027
7111
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCorePageThemeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7028
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCorePageThemeComponent, isStandalone: true, selector: "cide-core-page-theme", viewQueries: [{ propertyName: "themeDetailsRendererTemplate", first: true, predicate: ["themeDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "themeStatusRendererTemplate", first: true, predicate: ["themeStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack()\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-4 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\r\n <!-- Theme Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Theme Code -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Status -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n <!-- Sub Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Preview ID -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_preview_id_fm\" formControlName=\"sytm_preview_id_fm\" placeholder=\"Enter preview image ID\" label=\"Preview Image ID\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Description -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection: right-side checkbox list -->\r\n <div class=\"lg:tw-col-span-1 tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (getPreviewUrl(theme)) {\r\n <img [src]=\"getPreviewUrl(theme)\" class=\"tw-w-full tw-h-full tw-object-cover\" alt=\"Preview\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleJsonEditorComponent, selector: "cide-ele-json-editor", inputs: ["label", "helperText", "required", "disabled", "showCharacterCount", "config"], outputs: ["valueChange", "objectChange", "errorsChange", "validChange"] }] });
7112
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCorePageThemeComponent, isStandalone: true, selector: "cide-core-page-theme", viewQueries: [{ propertyName: "themeDetailsRendererTemplate", first: true, predicate: ["themeDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "themeStatusRendererTemplate", first: true, predicate: ["themeStatusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-2 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-2 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack();\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4\">\r\n <!-- Left Side: All Input Fields -->\r\n <div class=\"tw-space-y-4\">\r\n <!-- Row 1: Theme Title and Theme Code -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Row 2: Sub Title and Active Status -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <div class=\"tw-space-y-2 tw-flex tw-items-center\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Row 3: Description -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n </div>\r\n \r\n <!-- Right Side: File Upload -->\r\n <div class=\"tw-flex tw-flex-col tw-justify-start tw-items-center tw-p-0\">\r\n <cide-ele-file-input \r\n id=\"sytm_preview_id_fm\" \r\n formControlName=\"sytm_preview_id_fm\"\r\n accept=\"image/*\"\r\n [showPreview]=\"true\"\r\n [previewBoxMode]=\"true\"\r\n [showFileName]=\"false\"\r\n previewWidth=\"180px\"\r\n previewHeight=\"120px\"\r\n placeholderText=\"Upload Preview Image\"\r\n placeholderIcon=\"image\"\r\n [autoUpload]=\"true\"\r\n [uploadData]=\"getPreviewImageUploadData()\"\r\n (uploadSuccess)=\"onPreviewImageUploadSuccess($event)\"\r\n (uploadError)=\"onPreviewImageUploadError($event)\"\r\n (uploadProgressChange)=\"onPreviewImageUploadProgress($event)\">\r\n </cide-ele-file-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection -->\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\r\n <div class=\"tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n \r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (theme.sytm_preview_id_fm) {\r\n <img \r\n cideEleFileImage \r\n [fileId]=\"theme.sytm_preview_id_fm\" \r\n [altText]=\"'Theme Preview'\"\r\n class=\"tw-w-full tw-h-full tw-object-cover\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> ", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "component", type: CideEleJsonEditorComponent, selector: "cide-ele-json-editor", inputs: ["label", "helperText", "required", "disabled", "showCharacterCount", "config"], outputs: ["valueChange", "objectChange", "errorsChange", "validChange"] }, { kind: "component", type: CideEleFileInputComponent, selector: "cide-ele-file-input", inputs: ["label", "accept", "multiple", "disabled", "required", "helperText", "errorText", "showPreview", "previewWidth", "previewHeight", "previewBoxMode", "showFileName", "placeholderText", "placeholderIcon", "autoUpload", "uploadData"], outputs: ["fileChange", "uploadSuccess", "uploadError", "uploadProgressChange"] }, { kind: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }] });
7029
7113
  }
7030
7114
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCorePageThemeComponent, decorators: [{
7031
7115
  type: Component,
@@ -7040,7 +7124,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
7040
7124
  CideIconComponent,
7041
7125
  CideEleDropdownComponent,
7042
7126
  CideEleJsonEditorComponent,
7043
- ], template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack()\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-4 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\r\n <!-- Theme Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Theme Code -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Status -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n <!-- Sub Title -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Preview ID -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_preview_id_fm\" formControlName=\"sytm_preview_id_fm\" placeholder=\"Enter preview image ID\" label=\"Preview Image ID\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <!-- Description -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection: right-side checkbox list -->\r\n <div class=\"lg:tw-col-span-1 tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2 md:tw-col-span-3\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (getPreviewUrl(theme)) {\r\n <img [src]=\"getPreviewUrl(theme)\" class=\"tw-w-full tw-h-full tw-object-cover\" alt=\"Preview\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> " }]
7127
+ CideEleFileInputComponent,
7128
+ CideEleFileImageDirective,
7129
+ ], template: "<!-- Page Theme Container -->\r\n<div class=\"tw-flex tw-h-full tw-w-full\">\r\n \r\n <!-- Left: Form and header (60%) -->\r\n <div class=\"tw-w-full lg:tw-w-3/5 tw-flex tw-flex-col tw-border-r tw-border-gray-200\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-px-6 tw-py-2 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-2 sm:tw-space-y-0\">\r\n\r\n <!-- Title and Back Button -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-4\">\r\n <button cideEleButton variant=\"ghost\" size=\"sm\" (click)=\"goBack();\" class=\"tw-text-gray-600 hover:tw-text-gray-900\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">arrow_back</cide-ele-icon>\r\n </button>\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">palette</cide-ele-icon>\r\n <div>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Theme Management</h5>\r\n <p class=\"tw-text-sm tw-text-gray-500 tw-m-0\">Page: {{ pageTitle() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Quick Add/Edit Form Section -->\r\n <div class=\"tw-px-6 tw-py-3 tw-bg-white tw-overflow-auto\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">{{ isEditMode() ? 'edit' : 'add' }}</cide-ele-icon>\r\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-m-0\">{{ isEditMode() ? 'Edit Theme' : 'Quick Add Theme' }}</h6>\r\n </div>\r\n </div>\r\n\r\n <!-- Form (kept as-is) -->\r\n <form [formGroup]=\"themeForm\" (ngSubmit)=\"saveTheme()\" class=\"tw-space-y-4\">\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4\">\r\n <!-- Left Side: All Input Fields -->\r\n <div class=\"tw-space-y-4\">\r\n <!-- Row 1: Theme Title and Theme Code -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_title\" formControlName=\"sytm_title\" placeholder=\"Enter theme title\" label=\"Theme Title*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_theme_code\" formControlName=\"sytm_theme_code\" placeholder=\"Enter theme code\" label=\"Theme Code*\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Row 2: Sub Title and Active Status -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4\">\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-input id=\"sytm_sub_title\" formControlName=\"sytm_sub_title\" placeholder=\"Enter sub title\" label=\"Sub Title\" size=\"sm\"></cide-ele-input>\r\n </div>\r\n <div class=\"tw-space-y-2 tw-flex tw-items-center\">\r\n <cide-ele-input\r\n id=\"sytm_isactive_cb\"\r\n type=\"checkbox\"\r\n label=\"Active\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isactive\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Row 3: Description -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-textarea id=\"sytm_desc\" formControlName=\"sytm_desc\" placeholder=\"Enter theme description\" rows=\"2\" label=\"Description\" size=\"sm\"></cide-ele-textarea>\r\n </div>\r\n </div>\r\n \r\n <!-- Right Side: File Upload -->\r\n <div class=\"tw-flex tw-flex-col tw-justify-start tw-items-center tw-p-0\">\r\n <cide-ele-file-input \r\n id=\"sytm_preview_id_fm\" \r\n formControlName=\"sytm_preview_id_fm\"\r\n accept=\"image/*\"\r\n [showPreview]=\"true\"\r\n [previewBoxMode]=\"true\"\r\n [showFileName]=\"false\"\r\n previewWidth=\"180px\"\r\n previewHeight=\"120px\"\r\n placeholderText=\"Upload Preview Image\"\r\n placeholderIcon=\"image\"\r\n [autoUpload]=\"true\"\r\n [uploadData]=\"getPreviewImageUploadData()\"\r\n (uploadSuccess)=\"onPreviewImageUploadSuccess($event)\"\r\n (uploadError)=\"onPreviewImageUploadError($event)\"\r\n (uploadProgressChange)=\"onPreviewImageUploadProgress($event)\">\r\n </cide-ele-file-input>\r\n </div>\r\n </div>\r\n \r\n <!-- Configuration JSON -->\r\n <div class=\"tw-space-y-2\">\r\n <cide-ele-json-editor label=\"Configuration JSON\" formControlName=\"sytm_configuration\" [required]=\"true\" [config]=\"{\r\n showLineNumbers: true,\r\n autoFormat: true,\r\n validateOnChange: true,\r\n minHeight: 150,\r\n maxHeight: 300,\r\n placeholder: 'Enter theme configuration JSON...'\r\n }\" helperText=\"Enter valid JSON configuration for the theme\"></cide-ele-json-editor>\r\n </div>\r\n <!-- Layout Configuration + Selection -->\r\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\r\n <div class=\"tw-space-y-2\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Layout & Selection</div>\r\n <!-- Selected toggle -->\r\n <div class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-px-3 tw-py-2\">\r\n <cide-ele-input\r\n id=\"sytm_isselected\"\r\n type=\"checkbox\"\r\n label=\"Selected (Default)\"\r\n size=\"sm\"\r\n formControlName=\"sytm_isselected\">\r\n </cide-ele-input>\r\n </div>\r\n <div formGroupName=\"sytm_layout\" class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-md tw-divide-y tw-overflow-hidden\">\r\n <!-- Sidebar -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_sidebar\">\r\n <cide-ele-input id=\"layout_sidebar_status\" type=\"checkbox\" label=\"Sidebar\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Header -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_header\">\r\n <cide-ele-input id=\"layout_header_status\" type=\"checkbox\" label=\"Header\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Footer -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_footer\">\r\n <cide-ele-input id=\"layout_footer_status\" type=\"checkbox\" label=\"Footer\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Breadcrumb -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_breadcrumb\">\r\n <cide-ele-input id=\"layout_breadcrumb_status\" type=\"checkbox\" label=\"Breadcrumb\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Console -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_console\">\r\n <cide-ele-input id=\"layout_console_status\" type=\"checkbox\" label=\"Console\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n <!-- Request -->\r\n <div class=\"tw-px-3 tw-py-2\" formGroupName=\"sytm_layout_request\">\r\n <cide-ele-input id=\"layout_request_status\" type=\"checkbox\" label=\"Request\" size=\"sm\" formControlName=\"status\"></cide-ele-input>\r\n </div>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-pt-1\">Toggle active sections. Only one theme can be selected as default. More options can be added here later.</p>\r\n </div>\r\n \r\n <!-- Drawer Configuration -->\r\n <div class=\"tw-space-y-2\">\r\n <div class=\"tw-flex tw-items-center tw-justify-between\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Drawers</div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"outline\" (click)=\"addDrawer()\">\r\n Add Drawer\r\n </button>\r\n </div>\r\n\r\n <div formGroupName=\"sytm_layout\">\r\n <div class=\"tw-space-y-2\" formArrayName=\"sytm_layout_drawer\">\r\n <div *ngFor=\"let drawerGrp of drawerArray.controls; let i = index\" [formGroupName]=\"i\" class=\"tw-border tw-border-gray-200 tw-rounded-md tw-p-3 tw-flex tw-items-center tw-gap-3\">\r\n <cide-ele-input id=\"drawer_active_{{i}}\" type=\"checkbox\" label=\"Active\" size=\"sm\" formControlName=\"syth_status\"></cide-ele-input>\r\n <div class=\"tw-flex-1\">\r\n <cide-ele-select\r\n id=\"drawer_config_{{i}}\"\r\n label=\"Drawer For\"\r\n size=\"sm\"\r\n [options]=\"drawerConfigOptions\"\r\n formControlName=\"syth_config_syco_for\">\r\n </cide-ele-select>\r\n </div>\r\n <button cideEleButton type=\"button\" size=\"xs\" variant=\"ghost\" (click)=\"removeDrawer(i)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n <p class=\"tw-text-xs tw-text-gray-500\">Configure multiple drawers as needed.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-flex tw-flex-col tw-gap-2 tw-pt-4 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-items-center tw-justify-end tw-space-x-3\">\r\n <button cideEleButton type=\"button\" variant=\"outline\" (click)=\"cancelForm()\" [disabled]=\"loading()\">Cancel</button>\r\n <button cideEleButton type=\"submit\" variant=\"primary\" leftIcon=\"add\" [disabled]=\"!themeForm.valid || loading()\" [loading]=\"loading()\">\r\n {{ isEditMode() ? 'Update Theme' : 'Create Theme' }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Right: Theme gallery (40%) -->\r\n <div class=\"tw-hidden lg:tw-flex tw-w-2/5 tw-flex-col\">\r\n <!-- (Header consolidated above) -->\r\n\r\n <!-- Gallery list -->\r\n <div class=\"tw-flex-1 tw-overflow-auto tw-bg-gray-50\">\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-p-4\">\r\n @for (theme of filteredThemes(); track theme._id) {\r\n <div class=\"tw-rounded-md tw-transition tw-cursor-pointer tw-relative\"\r\n [ngClass]=\"theme.sytm_isselected\r\n ? 'tw-border tw-border-blue-500 tw-ring-2 tw-ring-blue-200 tw-bg-blue-50/50'\r\n : 'tw-bg-white tw-border tw-border-gray-200 hover:tw-shadow-sm'\"\r\n (click)=\"editTheme(theme)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-selected]=\"theme.sytm_isselected ? 'true' : 'false'\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\"\r\n (keydown.enter)=\"editTheme(theme)\"\r\n (keydown.space)=\"$event.preventDefault(); editTheme(theme)\">\r\n\r\n <!-- Selected badge -->\r\n <div *ngIf=\"theme.sytm_isselected\"\r\n class=\"tw-absolute tw-top-2 tw-right-2 tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-full tw-bg-blue-600 tw-text-white\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">check</cide-ele-icon>\r\n </div>\r\n \r\n <div class=\"tw-aspect-[16/9] tw-bg-gray-100 tw-rounded-t-md tw-overflow-hidden tw-flex tw-items-center tw-justify-center\">\r\n @if (theme.sytm_preview_id_fm) {\r\n <img \r\n cideEleFileImage \r\n [fileId]=\"theme.sytm_preview_id_fm\" \r\n [altText]=\"'Theme Preview'\"\r\n class=\"tw-w-full tw-h-full tw-object-cover\" />\r\n } @else {\r\n <div class=\"tw-text-gray-400 tw-text-xs\">No preview</div>\r\n }\r\n </div>\r\n <div class=\"tw-p-3 tw-space-y-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"theme.sytm_title\">{{ theme.sytm_title || 'Untitled Theme' }}</div>\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" [title]=\"theme.sytm_theme_code\">{{ theme.sytm_theme_code }}</div>\r\n <div class=\"tw-flex tw-items-center tw-justify-between tw-pt-1\">\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-text-xs\" [ngClass]=\"theme.sytm_isactive ? 'tw-text-green-700' : 'tw-text-red-700'\">\r\n <span class=\"tw-w-1.5 tw-h-1.5 tw-rounded-full\" [ngClass]=\"theme.sytm_isactive ? 'tw-bg-green-500' : 'tw-bg-red-500'\"></span>\r\n {{ theme.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n <div class=\"tw-flex tw-items-center tw-gap-1\">\r\n <!-- Set Selected Button - Clear and Simple -->\r\n @if (theme.sytm_isselected) {\r\n <span class=\"tw-inline-flex tw-items-center tw-gap-1 tw-px-2 tw-py-1 tw-bg-green-100 tw-text-green-800 tw-rounded-md tw-text-xs tw-font-medium\">\r\n <cide-ele-icon class=\"tw-w-3 tw-h-3\">check</cide-ele-icon>\r\n Selected\r\n </span>\r\n } @else {\r\n <button cideEleButton \r\n variant=\"outline\" \r\n size=\"xs\"\r\n (click)=\"$event.stopPropagation(); setSelectedTheme(theme)\"\r\n [attr.aria-label]=\"'Select ' + (theme.sytm_title || theme.sytm_theme_code) + ' theme'\"\r\n class=\"tw-text-xs\">\r\n Select\r\n </button>\r\n }\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); editTheme(theme)\"\r\n [attr.aria-label]=\"'Edit theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">edit</cide-ele-icon>\r\n </button>\r\n <button cideEleButton variant=\"ghost\" size=\"xs\" (click)=\"$event.stopPropagation(); deleteTheme(theme)\"\r\n [attr.aria-label]=\"'Delete theme ' + (theme.sytm_title || theme.sytm_theme_code)\">\r\n <cide-ele-icon class=\"tw-w-4 tw-h-4\">delete</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (!loading() && filteredThemes().length === 0) {\r\n <div class=\"tw-col-span-full tw-text-center tw-text-xs tw-text-gray-500 tw-py-8\">No themes found</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Template References for Grid Renderers (Best Practice)\r\n \r\n These ng-template elements represent the Angular best practice for custom rendering.\r\n They provide:\r\n - Type safety with template context\r\n - Component lifecycle integration\r\n - Change detection optimization\r\n - Proper event handling\r\n - Accessibility features\r\n \r\n Note: Current data grid uses string renderers for compatibility.\r\n Templates are maintained for future component enhancement.\r\n-->\r\n\r\n<!-- Theme Details Renderer Template -->\r\n<ng-template #themeDetailsRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <div class=\"tw-flex tw-items-center tw-min-w-0\">\r\n <!-- Theme Icon -->\r\n <div class=\"tw-flex-shrink-0\">\r\n <cide-ele-icon \r\n class=\"tw-text-purple-600\" \r\n size=\"xs\">\r\n palette\r\n </cide-ele-icon>\r\n </div>\r\n \r\n <!-- Theme Details -->\r\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\r\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\" \r\n [title]=\"row.sytm_title\">\r\n {{ row.sytm_title || 'Untitled' }}\r\n </div>\r\n @if (row.sytm_desc) {\r\n <div class=\"tw-text-xs tw-text-gray-500 tw-truncate\" \r\n [title]=\"row.sytm_desc\">\r\n {{ row.sytm_desc }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Theme Status Renderer Template -->\r\n<ng-template #themeStatusRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <span class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-whitespace-nowrap\"\r\n [ngClass]=\"row.sytm_isactive ? 'tw-bg-green-100 tw-text-green-800' : 'tw-bg-red-100 tw-text-red-800'\">\r\n {{ row.sytm_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Actions Dropdown Renderer Template -->\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template> " }]
7044
7130
  }] });
7045
7131
 
7046
7132
  var pageTheme_component = /*#__PURE__*/Object.freeze({
@@ -11005,11 +11091,13 @@ class CideCoreUserCreateComponent {
11005
11091
  // Dependency injection
11006
11092
  destroyRef = inject(DestroyRef);
11007
11093
  fb = inject(FormBuilder);
11094
+ cdr = inject(ChangeDetectorRef);
11008
11095
  userMasterService = inject(CideCoreUserMasterService);
11009
11096
  entityService = inject(CideCoreEntityManagementService);
11010
11097
  designationService = inject(CideCoreDesignationManagementService);
11011
11098
  departmentService = inject(CideCoreDepartmentManagementService);
11012
11099
  CideCoreGeneralMasterService = inject(CideCoreGeneralMasterService);
11100
+ generalMasterTypeService = inject(CideCoreGeneralMasterTypeService);
11013
11101
  pinCodeService = inject(CideCorePinCodeService);
11014
11102
  countryService = inject(CideCoreCountryService);
11015
11103
  userRoleService = inject(CideCoreUserRoleService);
@@ -11017,10 +11105,12 @@ class CideCoreUserCreateComponent {
11017
11105
  router = inject(Router);
11018
11106
  route = inject(ActivatedRoute);
11019
11107
  appState = inject(AppStateHelperService);
11108
+ floatingUploadService = inject(CideLytFloatingUploadService);
11020
11109
  userMasterForm;
11021
11110
  activeTab = signal('basic', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
11022
11111
  loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11023
11112
  error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
11113
+ success = signal(null, ...(ngDevMode ? [{ debugName: "success" }] : []));
11024
11114
  // User information from route
11025
11115
  userId = signal('', ...(ngDevMode ? [{ debugName: "userId" }] : []));
11026
11116
  isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
@@ -11032,6 +11122,92 @@ class CideCoreUserCreateComponent {
11032
11122
  familyDetails = signal([], ...(ngDevMode ? [{ debugName: "familyDetails" }] : []));
11033
11123
  entityMappings = signal([], ...(ngDevMode ? [{ debugName: "entityMappings" }] : []));
11034
11124
  menuRightsMap = signal({}, ...(ngDevMode ? [{ debugName: "menuRightsMap" }] : []));
11125
+ // User rights management
11126
+ userRightsTypeId = signal(null, ...(ngDevMode ? [{ debugName: "userRightsTypeId" }] : []));
11127
+ permissions = signal([], ...(ngDevMode ? [{ debugName: "permissions" }] : []));
11128
+ // Template helpers
11129
+ Object = Object;
11130
+ /**
11131
+ * Get address type label for header display
11132
+ */
11133
+ getAddressTypeLabel(addressIndex) {
11134
+ const addressTypeId = this.contactAddressesFormArray.at(addressIndex)?.get('sycad_address_type_id_sygms')?.value;
11135
+ if (addressTypeId) {
11136
+ const addressType = this.addressTypeOptions().find(option => option._id === addressTypeId);
11137
+ return addressType?.sygms_title || 'Address';
11138
+ }
11139
+ return 'Address';
11140
+ }
11141
+ /**
11142
+ * Handle address type change to update header
11143
+ */
11144
+ onAddressTypeChange(addressIndex) {
11145
+ // This method is called when address type changes to trigger header update
11146
+ // The header will automatically update due to change detection
11147
+ }
11148
+ /**
11149
+ * Get document type label for header display
11150
+ */
11151
+ getDocumentTypeLabel(documentIndex) {
11152
+ const documentTypeId = this.documentsFormArray.at(documentIndex)?.get('syusd_document_type_id_sygms')?.value;
11153
+ if (documentTypeId) {
11154
+ const documentType = this.documentTypeOptions().find(option => option._id === documentTypeId);
11155
+ return documentType?.sygms_title || 'Document';
11156
+ }
11157
+ return 'Document';
11158
+ }
11159
+ /**
11160
+ * Handle document type change to update header
11161
+ */
11162
+ onDocumentTypeChange(documentIndex) {
11163
+ // This method is called when document type changes to trigger header update
11164
+ // The header will automatically update due to change detection
11165
+ }
11166
+ /**
11167
+ * Handle document files selection
11168
+ */
11169
+ onDocumentFilesSelected(event, documentIndex) {
11170
+ const target = event.target;
11171
+ const files = target.files;
11172
+ if (!files || files.length === 0)
11173
+ return;
11174
+ console.log(`📎 Files selected for document ${documentIndex}:`, files);
11175
+ // Store files in the document form group or handle upload logic here
11176
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
11177
+ if (documentFormGroup) {
11178
+ // You can store the files in a custom property or handle upload immediately
11179
+ // For now, we'll store them in a custom property for display
11180
+ const existingFiles = this.getDocumentFiles(documentIndex);
11181
+ const newFiles = Array.from(files);
11182
+ const allFiles = [...existingFiles, ...newFiles];
11183
+ // Store files in the form group's custom property
11184
+ documentFormGroup._uploadedFiles = allFiles;
11185
+ console.log(`📎 Total files for document ${documentIndex}:`, allFiles.length);
11186
+ }
11187
+ }
11188
+ /**
11189
+ * Get document group ID
11190
+ */
11191
+ getDocumentGroupId(documentIndex) {
11192
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
11193
+ return documentFormGroup?.get('syusd_photo_group_id_cyfm')?.value || '';
11194
+ }
11195
+ /**
11196
+ * Get uploaded files for a document (legacy method for backward compatibility)
11197
+ */
11198
+ getDocumentFiles(documentIndex) {
11199
+ // For multiple file upload with group ID, we don't track individual files
11200
+ // Return empty array since files are managed by group ID
11201
+ return [];
11202
+ }
11203
+ /**
11204
+ * Remove a file from document (legacy method for backward compatibility)
11205
+ */
11206
+ removeDocumentFile(documentIndex, fileName) {
11207
+ // For multiple file upload with group ID, individual file removal is not supported
11208
+ // Files are managed as a group on the server
11209
+ console.log(`📎 Individual file removal not supported for group uploads. Document ${documentIndex}, File: ${fileName}`);
11210
+ }
11035
11211
  constructor() {
11036
11212
  this.userMasterForm = this.fb.group({
11037
11213
  // Basic User Information from auth_user_mst table
@@ -11093,7 +11269,8 @@ class CideCoreUserCreateComponent {
11093
11269
  syenm_activeupto: [''],
11094
11270
  syenm_isdefault: [false],
11095
11271
  syenm_isactive: [true],
11096
- syenm_isloggedin: [true]
11272
+ syenm_isloggedin: [true],
11273
+ exceptions: this.fb.array([]) // Add exceptions FormArray
11097
11274
  });
11098
11275
  }
11099
11276
  // Helper method to create contact address FormGroup
@@ -11116,20 +11293,22 @@ class CideCoreUserCreateComponent {
11116
11293
  }
11117
11294
  // Helper method to create document FormGroup
11118
11295
  createDocumentFormGroup() {
11119
- return this.fb.group({
11296
+ const formGroup = this.fb.group({
11120
11297
  _id: [''],
11298
+ syusd_user_id_user: [''],
11121
11299
  syusd_document_type_id_sygms: [''],
11122
11300
  syusd_doc_number: [''],
11123
11301
  syusd_doc_name_as_per_doc: [''],
11124
- syusd_photo_group_id_cyfm: [''],
11125
11302
  syusd_doc_issue_date: [''],
11126
11303
  syusd_doc_expiry_date: [''],
11304
+ syusd_photo_group_id_cyfm: [''],
11127
11305
  syusd_doc_verification_status_id_sygms: [''],
11128
- syusd_document_kyc_status_id_sygms: [''],
11129
- syusd_document_file_id_cyfm: [''],
11130
- syusd_document_remarks: [''],
11306
+ syusd_doc_kyc_status_id_sygms: [''],
11131
11307
  syusd_isactive: [true]
11132
11308
  });
11309
+ // Initialize file storage for this document
11310
+ formGroup._uploadedFiles = [];
11311
+ return formGroup;
11133
11312
  }
11134
11313
  // Helper method to create family detail FormGroup
11135
11314
  createFamilyDetailFormGroup() {
@@ -11213,7 +11392,7 @@ class CideCoreUserCreateComponent {
11213
11392
  }
11214
11393
  // Handle search change from the select component with debouncing
11215
11394
  onUserSearchChange(searchEvent, familyIndex) {
11216
- const query = searchEvent?.query || searchEvent || '';
11395
+ const query = searchEvent?.query;
11217
11396
  // Clear existing debounce timer for this family member
11218
11397
  if (this.searchDebounceTimers[familyIndex]) {
11219
11398
  clearTimeout(this.searchDebounceTimers[familyIndex]);
@@ -11239,7 +11418,7 @@ class CideCoreUserCreateComponent {
11239
11418
  }
11240
11419
  // Handle user selection change in the form
11241
11420
  onUserSelectionChange(event, familyIndex) {
11242
- const selectedUserId = event?.value || event;
11421
+ const selectedUserId = event?._id;
11243
11422
  if (selectedUserId) {
11244
11423
  // Find the selected user from the results for this specific family member
11245
11424
  const userResults = this.userSearchResults()[familyIndex] || [];
@@ -11258,26 +11437,124 @@ class CideCoreUserCreateComponent {
11258
11437
  designationOptions = signal({}, ...(ngDevMode ? [{ debugName: "designationOptions" }] : []));
11259
11438
  departmentOptions = signal({}, ...(ngDevMode ? [{ debugName: "departmentOptions" }] : []));
11260
11439
  menuOptions = signal([], ...(ngDevMode ? [{ debugName: "menuOptions" }] : []));
11261
- permissionOptions = signal([], ...(ngDevMode ? [{ debugName: "permissionOptions" }] : []));
11262
- entityRoleMap = signal({}, ...(ngDevMode ? [{ debugName: "entityRoleMap" }] : []));
11263
11440
  // Role permissions grid properties
11264
11441
  rolePermissionsGridConfig = signal({
11265
- id: 'role-permissions-grid',
11266
- columns: [],
11442
+ id: 'menu-list-grid',
11443
+ title: '',
11444
+ subtitle: '',
11445
+ columns: [
11446
+ {
11447
+ key: 'details',
11448
+ header: 'Menu Item',
11449
+ type: 'custom',
11450
+ width: 'auto',
11451
+ truncate: true,
11452
+ align: 'left',
11453
+ renderer: 'menuDetailsRenderer'
11454
+ },
11455
+ {
11456
+ key: 'syme_type',
11457
+ header: 'Type',
11458
+ type: 'custom',
11459
+ width: '120px',
11460
+ truncate: false,
11461
+ align: 'center',
11462
+ renderer: 'menuTypeRenderer'
11463
+ },
11464
+ {
11465
+ key: 'syme_path',
11466
+ header: 'Path',
11467
+ type: 'text',
11468
+ width: '200px',
11469
+ truncate: true,
11470
+ align: 'left'
11471
+ },
11472
+ {
11473
+ key: 'syme_isactive',
11474
+ header: 'Status',
11475
+ type: 'status',
11476
+ width: '100px',
11477
+ truncate: false,
11478
+ align: 'center',
11479
+ statusConfig: {
11480
+ activeValue: true,
11481
+ activeLabel: 'Active',
11482
+ inactiveLabel: 'Inactive',
11483
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
11484
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
11485
+ }
11486
+ },
11487
+ {
11488
+ key: 'syme_permissions_id_sygms',
11489
+ header: 'Permissions',
11490
+ type: 'custom',
11491
+ width: '200px',
11492
+ truncate: true,
11493
+ align: 'left',
11494
+ renderer: 'permissionsRenderer'
11495
+ },
11496
+ {
11497
+ key: 'actions',
11498
+ header: '',
11499
+ type: 'custom',
11500
+ width: '60px',
11501
+ truncate: false,
11502
+ align: 'center',
11503
+ renderer: 'actionsDropdownRenderer'
11504
+ }
11505
+ ],
11267
11506
  data: [],
11268
- pagination: { enabled: false, pageSize: 10, pageSizeOptions: [10, 25, 50, 100], showQuickJump: true, showPageInfo: true, showRefresh: true },
11269
- search: { enabled: true, placeholder: 'Search...', searchableColumns: [], debounceMs: 300 },
11270
- loading: { useDefer: false, skeletonRows: 5, showOverlay: false },
11271
- scroll: { enabled: true, maxHeight: '400px', minHeight: '200px', stickyHeader: true, virtualScroll: false, rowHeight: 25 },
11272
- dragDrop: { enabled: false, orderField: '', dragClass: '', dropClass: '' },
11507
+ trackBy: '_id',
11508
+ pagination: {
11509
+ enabled: false,
11510
+ pageSize: 10,
11511
+ pageSizeOptions: [10, 25, 50, 100],
11512
+ showQuickJump: true,
11513
+ showPageInfo: true,
11514
+ showRefresh: true
11515
+ },
11516
+ search: {
11517
+ enabled: true,
11518
+ placeholder: 'Search menu items...',
11519
+ searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
11520
+ debounceMs: 300
11521
+ },
11522
+ loading: {
11523
+ useDefer: true,
11524
+ skeletonRows: 5,
11525
+ showOverlay: false
11526
+ },
11527
+ scroll: {
11528
+ enabled: true,
11529
+ maxHeight: '',
11530
+ minHeight: '',
11531
+ stickyHeader: true,
11532
+ virtualScroll: false,
11533
+ rowHeight: 50
11534
+ },
11535
+ dragDrop: {
11536
+ enabled: true,
11537
+ orderField: 'syme_order_by',
11538
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
11539
+ dropClass: 'tw-bg-green-50'
11540
+ },
11273
11541
  responsive: true,
11274
11542
  striped: false,
11275
11543
  bordered: true,
11276
11544
  compact: false,
11277
- tableClass: '',
11278
- tree: { enabled: true, primaryKey: '_id', foreignKey: 'syme_parent_id_syme' }
11545
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
11546
+ onRefresh: 'onMenuItemRefresh',
11547
+ onRowReorder: 'onRowReorder',
11548
+ tree: {
11549
+ enabled: true,
11550
+ primaryKey: '_id',
11551
+ foreignKey: 'syme_id_syme',
11552
+ childrenKey: 'children',
11553
+ levelKey: 'level',
11554
+ expandedKey: 'isExpanded',
11555
+ hasChildrenKey: 'hasChildren'
11556
+ }
11279
11557
  }, ...(ngDevMode ? [{ debugName: "rolePermissionsGridConfig" }] : []));
11280
- selectedRolePermissions = signal([], ...(ngDevMode ? [{ debugName: "selectedRolePermissions" }] : []));
11281
11558
  selectedRoleId = signal(null, ...(ngDevMode ? [{ debugName: "selectedRoleId" }] : []));
11282
11559
  selectedEntityIndex = signal(null, ...(ngDevMode ? [{ debugName: "selectedEntityIndex" }] : []));
11283
11560
  // Template renderers for role permissions grid
@@ -11285,6 +11562,7 @@ class CideCoreUserCreateComponent {
11285
11562
  permissionsCheckboxRendererTemplate = viewChild('permissionsCheckboxRendererTemplate', ...(ngDevMode ? [{ debugName: "permissionsCheckboxRendererTemplate" }] : []));
11286
11563
  menuTypeRendererTemplate = viewChild('menuTypeRendererTemplate', ...(ngDevMode ? [{ debugName: "menuTypeRendererTemplate" }] : []));
11287
11564
  menuRightsPermissionsRendererTemplate = viewChild('menuRightsPermissionsRendererTemplate', ...(ngDevMode ? [{ debugName: "menuRightsPermissionsRendererTemplate" }] : []));
11565
+ permissionsRendererTemplate = viewChild('permissionsRendererTemplate', ...(ngDevMode ? [{ debugName: "permissionsRendererTemplate" }] : []));
11288
11566
  addressTypeOptions = signal([], ...(ngDevMode ? [{ debugName: "addressTypeOptions" }] : []));
11289
11567
  // Document and Family dropdown options
11290
11568
  documentTypeOptions = signal([], ...(ngDevMode ? [{ debugName: "documentTypeOptions" }] : []));
@@ -11327,12 +11605,25 @@ class CideCoreUserCreateComponent {
11327
11605
  }
11328
11606
  // Always load dropdown options
11329
11607
  this.loadDropdownOptions();
11608
+ this.loadUserRightsTypeId(); // Load user rights type and permissions
11330
11609
  this.setupFormSubscriptions();
11331
11610
  this.setEntityIdFromAppState();
11611
+ // Set up floating uploader with current user ID
11612
+ this.setupFloatingUploader();
11332
11613
  // Load initial users for family member selection
11333
11614
  this.loadInitialUsers();
11334
11615
  });
11335
11616
  }
11617
+ /**
11618
+ * Setup floating uploader with current user ID
11619
+ */
11620
+ setupFloatingUploader() {
11621
+ // Get current user ID from app state or use a default
11622
+ const currentUser = this.appState.getCurrentUser();
11623
+ const currentUserId = currentUser?._id || 'current-user';
11624
+ this.floatingUploadService.setCurrentUserId(currentUserId);
11625
+ console.log('🚀 [UserCreate] Floating uploader setup with user ID:', currentUserId);
11626
+ }
11336
11627
  /**
11337
11628
  * Setup form subscriptions
11338
11629
  */
@@ -11541,9 +11832,42 @@ class CideCoreUserCreateComponent {
11541
11832
  mappingGroup.get('syenm_entity_id_syen')?.disable();
11542
11833
  entityMappingFormArray.push(mappingGroup);
11543
11834
  });
11835
+ // Load role permissions for each mapping that has a role selected
11836
+ data.core_entity_mapping.forEach((mapping, index) => {
11837
+ if (mapping.syenm_role_id_syusrol) {
11838
+ const roleId = typeof mapping.syenm_role_id_syusrol === 'object'
11839
+ ? mapping.syenm_role_id_syusrol._id
11840
+ : mapping.syenm_role_id_syusrol;
11841
+ if (roleId) {
11842
+ console.log(`🎭 Loading role permissions for mapping ${index} with role ${roleId}`);
11843
+ this.loadRolePermissions(roleId, index);
11844
+ }
11845
+ }
11846
+ });
11544
11847
  }
11545
- if (data.menu_rights) {
11546
- this.menuRightsMap.set(data.menu_rights);
11848
+ // Handle existing role exceptions
11849
+ if (data.core_user_role_exceptions && Array.isArray(data.core_user_role_exceptions)) {
11850
+ console.log('🎭 Loading existing role exceptions:', data.core_user_role_exceptions);
11851
+ // Group exceptions by mapping index
11852
+ const exceptionsByMapping = {};
11853
+ data.core_user_role_exceptions.forEach((exception) => {
11854
+ // Find the mapping index for this exception
11855
+ const mappingIndex = this.findMappingIndexByEntityMappingId(exception.syusrex_user_entity_mapping_id_syenm || '');
11856
+ if (mappingIndex !== null) {
11857
+ if (!exceptionsByMapping[mappingIndex.toString()]) {
11858
+ exceptionsByMapping[mappingIndex.toString()] = [];
11859
+ }
11860
+ exceptionsByMapping[mappingIndex.toString()].push(exception);
11861
+ }
11862
+ });
11863
+ // Add exceptions to each mapping
11864
+ Object.keys(exceptionsByMapping).forEach(mappingIndexStr => {
11865
+ const mappingIndex = parseInt(mappingIndexStr);
11866
+ const mapping = this.entityMappings()[mappingIndex];
11867
+ if (mapping) {
11868
+ mapping.exceptions = exceptionsByMapping[mappingIndexStr];
11869
+ }
11870
+ });
11547
11871
  }
11548
11872
  if (data.core_user_contact_addresses) {
11549
11873
  this.contactAddresses.set(data.core_user_contact_addresses);
@@ -11578,6 +11902,7 @@ class CideCoreUserCreateComponent {
11578
11902
  const documentGroup = this.createDocumentFormGroup();
11579
11903
  documentGroup.patchValue({
11580
11904
  _id: document._id || '',
11905
+ syusd_user_id_user: this.appState.getUserId() || '',
11581
11906
  syusd_document_type_id_sygms: document.syusd_document_type_id_sygms?._id || '',
11582
11907
  syusd_doc_number: document.syusd_doc_number || '',
11583
11908
  syusd_doc_name_as_per_doc: document.syusd_doc_name_as_per_doc || '',
@@ -11585,9 +11910,7 @@ class CideCoreUserCreateComponent {
11585
11910
  syusd_doc_issue_date: document.syusd_doc_issue_date || '',
11586
11911
  syusd_doc_expiry_date: document.syusd_doc_expiry_date || '',
11587
11912
  syusd_doc_verification_status_id_sygms: document.syusd_doc_verification_status_id_sygms?._id || '',
11588
- syusd_document_kyc_status_id_sygms: document.syusd_document_kyc_status_id_sygms?._id || '',
11589
- syusd_document_file_id_cyfm: document.syusd_document_file_id_cyfm || '',
11590
- syusd_document_remarks: document.syusd_document_remarks || '',
11913
+ syusd_doc_kyc_status_id_sygms: document.syusd_doc_kyc_status_id_sygms?._id || '',
11591
11914
  syusd_isactive: document.syusd_isactive ?? true
11592
11915
  });
11593
11916
  this.documentsFormArray.push(documentGroup);
@@ -11643,25 +11966,8 @@ class CideCoreUserCreateComponent {
11643
11966
  this.loadDocumentKycStatus();
11644
11967
  this.loadBloodGroups();
11645
11968
  this.loadRelationshipOptions();
11646
- // Load menu options (simulated data)
11647
- this.menuOptions.set([
11648
- { value: 'user-management', label: 'User Management', menu_code: 'USRMGT' },
11649
- { value: 'entity-management', label: 'Entity Management', menu_code: 'ENTMGT' },
11650
- { value: 'role-management', label: 'Role Management', menu_code: 'ROLMGT' },
11651
- { value: 'reports', label: 'Reports', menu_code: 'RPTS' },
11652
- { value: 'settings', label: 'Settings', menu_code: 'STGS' },
11653
- { value: 'dashboard', label: 'Dashboard', menu_code: 'DASH' },
11654
- { value: 'file-manager', label: 'File Manager', menu_code: 'FMGR' }
11655
- ]);
11656
- // Load permission options (simulated data)
11657
- this.permissionOptions.set([
11658
- { value: 'create', label: 'Create' },
11659
- { value: 'read', label: 'Read' },
11660
- { value: 'update', label: 'Update' },
11661
- { value: 'delete', label: 'Delete' },
11662
- { value: 'approve', label: 'Approve' },
11663
- { value: 'reject', label: 'Reject' }
11664
- ]);
11969
+ // Load menu options from API
11970
+ this.loadMenuOptions();
11665
11971
  }
11666
11972
  relationshipOptions() {
11667
11973
  return this.relationshipOptionsData();
@@ -11727,6 +12033,12 @@ class CideCoreUserCreateComponent {
11727
12033
  }
11728
12034
  // Trigger change detection to update other entity dropdowns
11729
12035
  this.triggerEntityDropdownUpdate();
12036
+ // Automatically load menu rights when both entity and role are selected
12037
+ const mapping = this.entityMappings()[mappingIndex];
12038
+ if (mapping?.syenm_entity_id_syen && mapping?.syenm_role_id_syusrol) {
12039
+ console.log(`🚀 Auto-loading menu rights for mapping ${mappingIndex}`);
12040
+ this.loadMenuRights(mappingIndex);
12041
+ }
11730
12042
  // For now, we'll use all available roles
11731
12043
  // In a real implementation, you'd filter roles based on the entity
11732
12044
  }
@@ -11981,10 +12293,9 @@ class CideCoreUserCreateComponent {
11981
12293
  */
11982
12294
  initializeRolePermissionsGrid() {
11983
12295
  this.rolePermissionsGridConfig.set({
11984
- id: 'role-permissions-grid',
11985
- title: 'Role Permissions',
11986
- subtitle: 'Select permissions for the chosen role',
11987
- fullHeight: true,
12296
+ id: 'menu-list-grid',
12297
+ title: '',
12298
+ subtitle: '',
11988
12299
  columns: [
11989
12300
  {
11990
12301
  key: 'details',
@@ -12004,14 +12315,46 @@ class CideCoreUserCreateComponent {
12004
12315
  align: 'center',
12005
12316
  renderer: 'menuTypeRenderer'
12006
12317
  },
12318
+ {
12319
+ key: 'syme_path',
12320
+ header: 'Path',
12321
+ type: 'text',
12322
+ width: '200px',
12323
+ truncate: true,
12324
+ align: 'left'
12325
+ },
12326
+ {
12327
+ key: 'syme_isactive',
12328
+ header: 'Status',
12329
+ type: 'status',
12330
+ width: '100px',
12331
+ truncate: false,
12332
+ align: 'center',
12333
+ statusConfig: {
12334
+ activeValue: true,
12335
+ activeLabel: 'Active',
12336
+ inactiveLabel: 'Inactive',
12337
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
12338
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
12339
+ }
12340
+ },
12007
12341
  {
12008
12342
  key: 'syme_permissions_id_sygms',
12009
- header: 'Available Permissions',
12343
+ header: 'Permissions',
12010
12344
  type: 'custom',
12011
- width: '300px',
12012
- truncate: false,
12345
+ width: '200px',
12346
+ truncate: true,
12013
12347
  align: 'left',
12014
- renderer: 'permissionsCheckboxRenderer'
12348
+ renderer: 'permissionsRenderer'
12349
+ },
12350
+ {
12351
+ key: 'actions',
12352
+ header: '',
12353
+ type: 'custom',
12354
+ width: '60px',
12355
+ truncate: false,
12356
+ align: 'center',
12357
+ renderer: 'actionsDropdownRenderer'
12015
12358
  }
12016
12359
  ],
12017
12360
  data: [],
@@ -12031,20 +12374,20 @@ class CideCoreUserCreateComponent {
12031
12374
  debounceMs: 300
12032
12375
  },
12033
12376
  loading: {
12034
- useDefer: false,
12377
+ useDefer: true,
12035
12378
  skeletonRows: 5,
12036
12379
  showOverlay: false
12037
12380
  },
12038
12381
  scroll: {
12039
12382
  enabled: true,
12040
- maxHeight: '400px',
12041
- minHeight: '200px',
12383
+ maxHeight: '',
12384
+ minHeight: '',
12042
12385
  stickyHeader: true,
12043
12386
  virtualScroll: false,
12044
- rowHeight: 25
12387
+ rowHeight: 50
12045
12388
  },
12046
12389
  dragDrop: {
12047
- enabled: false,
12390
+ enabled: true,
12048
12391
  orderField: 'syme_order_by',
12049
12392
  dragClass: 'tw-opacity-50 tw-bg-blue-50',
12050
12393
  dropClass: 'tw-bg-green-50'
@@ -12054,10 +12397,16 @@ class CideCoreUserCreateComponent {
12054
12397
  bordered: true,
12055
12398
  compact: false,
12056
12399
  tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
12400
+ onRefresh: 'onMenuItemRefresh',
12401
+ onRowReorder: 'onRowReorder',
12057
12402
  tree: {
12058
12403
  enabled: true,
12059
12404
  primaryKey: '_id',
12060
- foreignKey: 'syme_parent_id_syme'
12405
+ foreignKey: 'syme_id_syme',
12406
+ childrenKey: 'children',
12407
+ levelKey: 'level',
12408
+ expandedKey: 'isExpanded',
12409
+ hasChildrenKey: 'hasChildren'
12061
12410
  }
12062
12411
  });
12063
12412
  }
@@ -12073,12 +12422,22 @@ class CideCoreUserCreateComponent {
12073
12422
  this.selectedEntityIndex.set(mappingIndex);
12074
12423
  this.selectedRoleId.set(roleId);
12075
12424
  // Load role details and permissions
12076
- this.loadRolePermissions(roleId);
12425
+ this.loadRolePermissions(roleId, mappingIndex);
12426
+ // Automatically load menu rights when both entity and role are selected
12427
+ const mapping = this.entityMappings()[mappingIndex];
12428
+ if (mapping?.syenm_entity_id_syen && mapping?.syenm_role_id_syusrol) {
12429
+ console.log(`🚀 Auto-loading menu rights for mapping ${mappingIndex}`);
12430
+ this.loadMenuRights(mappingIndex);
12431
+ // Force refresh the grid to show updated permission states
12432
+ setTimeout(() => {
12433
+ this.cdr.detectChanges();
12434
+ }, 100);
12435
+ }
12077
12436
  }
12078
12437
  /**
12079
12438
  * Load role permissions from API
12080
12439
  */
12081
- loadRolePermissions(roleId) {
12440
+ loadRolePermissions(roleId, mappingIndex) {
12082
12441
  console.log(`🎭 Loading permissions for role:`, roleId);
12083
12442
  this.loading.set(true);
12084
12443
  // Load role details by ID
@@ -12086,8 +12445,8 @@ class CideCoreUserCreateComponent {
12086
12445
  next: (response) => {
12087
12446
  if (response?.success && response.data) {
12088
12447
  console.log(`🎭 Role details loaded:`, response.data);
12089
- // Load menus and permissions for the role
12090
- this.loadMenusAndPermissionsForRole(response.data);
12448
+ // Store role permissions for simple lookup
12449
+ this.storeRolePermissions(response.data, mappingIndex);
12091
12450
  }
12092
12451
  else {
12093
12452
  console.error(`❌ Failed to load role details:`, response);
@@ -12103,119 +12462,109 @@ class CideCoreUserCreateComponent {
12103
12462
  });
12104
12463
  }
12105
12464
  /**
12106
- * Load menus and permissions for the selected role
12107
- */
12108
- loadMenusAndPermissionsForRole(roleData) {
12109
- console.log(`🎭 Loading menus and permissions for role:`, roleData);
12110
- // Load menus from API
12111
- this.loadMenusFromAPI().then(() => {
12112
- // Load permissions from general master
12113
- this.loadPermissionsFromAPI().then(() => {
12114
- // Build the tree structure with role permissions
12115
- this.buildRolePermissionsTree(roleData);
12116
- });
12117
- });
12118
- }
12119
- /**
12120
- * Load menus from API
12465
+ * Update permission values for a specific menu row
12121
12466
  */
12122
- loadMenusFromAPI() {
12123
- return new Promise((resolve, reject) => {
12124
- if (!this.menuService) {
12125
- console.error('❌ MenuService is not available');
12126
- reject('MenuService not available');
12127
- return;
12128
- }
12129
- const requestBody = {
12130
- pagination: false,
12131
- sort: { order: 'asc', key: 'syme_order_by' }
12132
- };
12133
- this.menuService.getMenuList(requestBody).subscribe({
12134
- next: (response) => {
12135
- if (response?.success) {
12136
- console.log(`🎭 Menus loaded:`, response.data);
12137
- this.menuOptions.set(response.data || []);
12138
- resolve();
12139
- }
12140
- else {
12141
- console.error(`❌ Failed to load menus:`, response);
12142
- reject('Failed to load menus');
12467
+ updateMenuPermissionValues(mappingIndex, menuId) {
12468
+ this.menuRightsMap.update(map => {
12469
+ const newMap = { ...map };
12470
+ const menuRights = newMap[mappingIndex.toString()] || [];
12471
+ const updatedMenuRights = menuRights.map(menu => {
12472
+ if (menu._id === menuId) {
12473
+ // Re-compute permission values for this menu
12474
+ const permissionValues = {};
12475
+ if (menu.syme_permissions_id_sygms) {
12476
+ menu.syme_permissions_id_sygms.forEach(permissionId => {
12477
+ const permission = this.getPermissionById(permissionId);
12478
+ if (permission) {
12479
+ permissionValues[permissionId] = {
12480
+ checked: this.getFormControlValue(menu, permissionId),
12481
+ permission: permission
12482
+ };
12483
+ }
12484
+ });
12143
12485
  }
12144
- },
12145
- error: (error) => {
12146
- console.error(`❌ Error loading menus:`, error);
12147
- reject(error);
12486
+ return {
12487
+ ...menu,
12488
+ _permissionValues: permissionValues
12489
+ };
12148
12490
  }
12491
+ return menu;
12149
12492
  });
12493
+ newMap[mappingIndex.toString()] = updatedMenuRights;
12494
+ return newMap;
12150
12495
  });
12151
12496
  }
12152
12497
  /**
12153
- * Load permissions from API
12498
+ * Store role permissions for simple lookup
12154
12499
  */
12155
- loadPermissionsFromAPI() {
12156
- return new Promise((resolve, reject) => {
12157
- // Load permissions from general master
12158
- this.CideCoreGeneralMasterService.generalMasterList$.subscribe({
12159
- next: (response) => {
12160
- if (response?.success) {
12161
- console.log(`🎭 Permissions loaded:`, response.data);
12162
- this.permissionOptions.set(response.data || []);
12163
- resolve();
12164
- }
12165
- else {
12166
- console.error(`❌ Failed to load permissions:`, response);
12167
- reject('Failed to load permissions');
12500
+ storeRolePermissions(roleData, mappingIndex) {
12501
+ console.log(`🎭 Storing role permissions for mapping ${mappingIndex}:`, roleData);
12502
+ // Extract role permissions from the role data
12503
+ const roleRights = roleData.core_user_role_rights;
12504
+ if (roleRights && Array.isArray(roleRights)) {
12505
+ // Store role permissions as objects with ID and title
12506
+ const rolePermissionObjects = roleRights.map((right) => {
12507
+ const permission = right.syusrgt_role_permissions_id_sygms;
12508
+ return {
12509
+ _id: permission?._id,
12510
+ sygms_title: permission?.sygms_title,
12511
+ menu_id: right.syusrgt_menu_id_syme?._id
12512
+ };
12513
+ }).filter((permission) => permission._id && permission.sygms_title);
12514
+ // Update menuRightsMap with role permissions for each menu
12515
+ this.menuRightsMap.update(menuMap => {
12516
+ const newMenuMap = { ...menuMap };
12517
+ const currentMenuRights = newMenuMap[mappingIndex.toString()] || [];
12518
+ // Update each menu with its role permissions
12519
+ const updatedMenuRights = currentMenuRights.map(menu => {
12520
+ if (menu._id) {
12521
+ const menuSpecificPermissions = rolePermissionObjects
12522
+ .filter(permission =>
12523
+ // Permission must be in the menu's allowed permissions list
12524
+ menu.syme_permissions_id_sygms?.includes(permission._id) &&
12525
+ // AND must be assigned to this menu in the role data
12526
+ permission.menu_id === menu._id);
12527
+ return {
12528
+ ...menu,
12529
+ _rolePermissions: menuSpecificPermissions
12530
+ };
12168
12531
  }
12169
- },
12170
- error: (error) => {
12171
- console.error(`❌ Error loading permissions:`, error);
12172
- reject(error);
12532
+ return menu;
12533
+ });
12534
+ newMenuMap[mappingIndex.toString()] = updatedMenuRights;
12535
+ return newMenuMap;
12536
+ });
12537
+ // Update permission values for all menus in this mapping
12538
+ const menuRights = this.menuRightsMap()[mappingIndex.toString()] || [];
12539
+ menuRights.forEach(menu => {
12540
+ if (menu._id) {
12541
+ this.updateMenuPermissionValues(mappingIndex, menu._id);
12173
12542
  }
12174
12543
  });
12175
- });
12544
+ console.log(`🎭 Stored role permission objects for mapping ${mappingIndex}:`, rolePermissionObjects);
12545
+ }
12546
+ else {
12547
+ console.log(`🎭 No role permissions found in role data`);
12548
+ }
12176
12549
  }
12177
12550
  /**
12178
- * Build role permissions tree structure
12179
- */
12180
- buildRolePermissionsTree(roleData) {
12181
- console.log(`🎭 Building permissions tree for role:`, roleData);
12182
- const menus = this.menuOptions();
12183
- const permissions = this.permissionOptions();
12184
- // Create a map of role permissions for quick lookup
12185
- const rolePermissionsMap = new Map();
12186
- if (roleData.roleRights && Array.isArray(roleData.roleRights)) {
12187
- roleData.roleRights.forEach((right) => {
12188
- const key = `${right.syusrgt_menu_id_syme}_${right.syusrgt_role_permissions_id_sygms}`;
12189
- rolePermissionsMap.set(key, right);
12190
- });
12191
- }
12192
- // Build tree structure with permissions
12193
- const treeData = menus.map(menu => ({
12194
- ...menu,
12195
- permissions: permissions.map(permission => ({
12196
- ...permission,
12197
- isSelected: rolePermissionsMap.has(`${menu._id}_${permission._id}`)
12198
- }))
12199
- }));
12200
- console.log(`🎭 Tree data built:`, treeData);
12201
- this.selectedRolePermissions.set(treeData);
12202
- // Update grid data
12203
- this.rolePermissionsGridConfig.update(config => ({
12204
- ...config,
12205
- data: treeData
12206
- }));
12207
- }
12208
- /**
12209
- * Clear role permissions
12551
+ * Clear role permissions
12210
12552
  */
12211
12553
  clearRolePermissions() {
12212
- this.selectedRolePermissions.set([]);
12213
12554
  this.selectedRoleId.set(null);
12214
12555
  this.selectedEntityIndex.set(null);
12215
- this.rolePermissionsGridConfig.update(config => ({
12216
- ...config,
12217
- data: []
12218
- }));
12556
+ }
12557
+ /**
12558
+ * Find mapping index by entity mapping ID
12559
+ */
12560
+ findMappingIndexByEntityMappingId(entityMappingId) {
12561
+ const mappings = this.entityMappings();
12562
+ for (let i = 0; i < mappings.length; i++) {
12563
+ if (mappings[i]._id === entityMappingId) {
12564
+ return i;
12565
+ }
12566
+ }
12567
+ return null;
12219
12568
  }
12220
12569
  /**
12221
12570
  * Handle grid events for role permissions
@@ -12247,20 +12596,272 @@ class CideCoreUserCreateComponent {
12247
12596
  * Get permission by ID
12248
12597
  */
12249
12598
  getPermissionById(permissionId) {
12250
- return this.permissionOptions().find(permission => permission._id === permissionId);
12599
+ return this.permissions().find(permission => permission._id === permissionId);
12251
12600
  }
12252
12601
  /**
12253
- * Check if permission is selected for a menu
12602
+ * Check if permission is available in the selected role for a specific menu
12254
12603
  */
12255
- isPermissionSelected(menuId, permissionId) {
12256
- const rolePermissions = this.selectedRolePermissions();
12257
- const menu = rolePermissions.find(m => m._id === menuId);
12258
- if (menu && menu.permissions) {
12259
- const permission = menu.permissions.find((p) => p._id === permissionId);
12260
- return permission ? permission.isSelected : false;
12604
+ isPermissionInRole(permissionId, mappingIndex, menuId) {
12605
+ const mapping = this.entityMappings()[mappingIndex];
12606
+ const roleId = mapping?.syenm_role_id_syusrol;
12607
+ console.log(`🎭 Checking permission ${permissionId} for role:`, roleId, 'menu:', menuId);
12608
+ if (!roleId || !menuId) {
12609
+ console.log(`🎭 No role ID or menu ID found for mapping ${mappingIndex}`);
12610
+ return false;
12261
12611
  }
12612
+ // Get role permissions from the menu objects in menuRightsMap
12613
+ const menuRights = this.menuRightsMap()[mappingIndex.toString()] || [];
12614
+ const menu = menuRights.find(m => m._id === menuId);
12615
+ if (menu && menu._rolePermissions) {
12616
+ const rolePermissions = menu._rolePermissions;
12617
+ const isInRole = rolePermissions.some((permission) => permission._id === permissionId && permission.menu_id === menuId);
12618
+ console.log(`🎭 Permission ${permissionId} in role for menu ${menuId}: ${isInRole}`);
12619
+ return isInRole;
12620
+ }
12621
+ console.log(`🎭 No role permissions found for mapping ${mappingIndex}, menu ${menuId}`);
12262
12622
  return false;
12263
12623
  }
12624
+ /**
12625
+ * Get form control value for a permission
12626
+ */
12627
+ getFormControlValue(row, permissionId) {
12628
+ console.log(`🎭 Getting form control value for permission: ${permissionId} for menu: ${row.syme_title}`, row);
12629
+ const permission = this.getPermissionById(permissionId);
12630
+ if (!permission) {
12631
+ console.log(`🎭 Permission not found for ID: ${permissionId}`);
12632
+ return false;
12633
+ }
12634
+ // Find the current mapping index
12635
+ const mappingIndex = this.getCurrentMappingIndex();
12636
+ if (mappingIndex === null) {
12637
+ console.log(`🎭 No current mapping index found`);
12638
+ return false;
12639
+ }
12640
+ // Check if permission is available in the role for this specific menu
12641
+ const isRolePermission = this.isPermissionInRole(permissionId, mappingIndex, row._id);
12642
+ console.log(`🎭 Permission ${permission.sygms_title} for menu ${row.syme_title}: isRolePermission = ${isRolePermission}`);
12643
+ if (isRolePermission) {
12644
+ // If permission is in role, it should be checked by default
12645
+ console.log(`🎭 Returning true for role permission: ${permission.sygms_title}`);
12646
+ return true;
12647
+ }
12648
+ else {
12649
+ // If permission is not in role, check if it's added as exception
12650
+ const mapping = this.entityMappings()[mappingIndex];
12651
+ const exceptions = mapping.exceptions || [];
12652
+ const isException = exceptions.some((exception) => exception.syusrex_menu_id_syme === row._id &&
12653
+ exception.syusrex_role_permissions_id_sygms === permissionId);
12654
+ console.log(`🎭 Permission ${permission.sygms_title} is exception: ${isException}`);
12655
+ return isException;
12656
+ }
12657
+ }
12658
+ /**
12659
+ * Handle permission change with type safety
12660
+ */
12661
+ onPermissionChangeSafe(checked, row, permissionId) {
12662
+ this.onPermissionChange(Boolean(checked), row, permissionId);
12663
+ }
12664
+ /**
12665
+ * Handle permission change
12666
+ */
12667
+ onPermissionChange(checked, row, permissionId) {
12668
+ const permission = this.getPermissionById(permissionId);
12669
+ if (!permission)
12670
+ return;
12671
+ // Find the current mapping index
12672
+ const mappingIndex = this.getCurrentMappingIndex();
12673
+ if (mappingIndex === null)
12674
+ return;
12675
+ // Check if permission is in role for this specific menu
12676
+ const isRolePermission = this.isPermissionInRole(permissionId, mappingIndex, row._id);
12677
+ if (isRolePermission) {
12678
+ // Role permissions are handled by the role itself, no form controls needed
12679
+ console.log('🎭 Role permission (handled by role):', {
12680
+ menu: row.syme_title,
12681
+ permission: permission.sygms_title,
12682
+ checked: checked
12683
+ });
12684
+ }
12685
+ else {
12686
+ // Handle exception permission
12687
+ if (checked) {
12688
+ // Add exception
12689
+ this.addRoleException(mappingIndex, row._id || '', permissionId);
12690
+ }
12691
+ else {
12692
+ // Remove exception
12693
+ this.removeRoleException(mappingIndex, row._id || '', permissionId);
12694
+ }
12695
+ console.log('🎭 Exception permission changed:', {
12696
+ menu: row.syme_title,
12697
+ permission: permission.sygms_title,
12698
+ checked: checked
12699
+ });
12700
+ }
12701
+ // Update the pre-computed permission values for this menu
12702
+ this.updateMenuPermissionValues(mappingIndex, row._id || '');
12703
+ }
12704
+ /**
12705
+ * Handle permission change for specific mapping
12706
+ */
12707
+ onPermissionChangeForMapping(checked, row, permissionId, mappingIndex) {
12708
+ const permission = this.getPermissionById(permissionId);
12709
+ if (!permission)
12710
+ return;
12711
+ const controlName = `core_entity_mapping.${mappingIndex}.menu_rights.${row._id}.${permission.sygms_title}`;
12712
+ this.userMasterForm.get(controlName)?.setValue(checked);
12713
+ console.log('🎭 Permission changed for mapping:', {
12714
+ mappingIndex,
12715
+ menu: row.syme_title,
12716
+ permission: permission.sygms_title,
12717
+ checked: checked,
12718
+ controlName
12719
+ });
12720
+ }
12721
+ /**
12722
+ * Get current mapping index (helper method)
12723
+ */
12724
+ getCurrentMappingIndex() {
12725
+ // Find the mapping index that has both entity and role selected
12726
+ const entityMappings = this.entityMappings();
12727
+ for (let i = 0; i < entityMappings.length; i++) {
12728
+ const entityId = this.userMasterForm.get(`core_entity_mapping.${i}.syenm_entity_id_syen`)?.value;
12729
+ const roleId = this.userMasterForm.get(`core_entity_mapping.${i}.syenm_role_id_syusrol`)?.value;
12730
+ if (entityId && roleId) {
12731
+ return i;
12732
+ }
12733
+ }
12734
+ return null;
12735
+ }
12736
+ /**
12737
+ * Add role exception
12738
+ */
12739
+ addRoleException(mappingIndex, menuId, permissionId) {
12740
+ const mapping = this.entityMappings()[mappingIndex];
12741
+ const permission = this.getPermissionById(permissionId);
12742
+ if (!mapping || !permission)
12743
+ return;
12744
+ // Get the role ID directly (not as object)
12745
+ const roleId = typeof mapping.syenm_role_id_syusrol === 'object'
12746
+ ? mapping.syenm_role_id_syusrol?._id ?? ''
12747
+ : mapping.syenm_role_id_syusrol ?? '';
12748
+ // Create exception object with change tracking
12749
+ const exception = {
12750
+ syusrex_user_entity_mapping_id_syenm: mapping._id || '',
12751
+ syusrex_role_id_syusrol: roleId, // Direct ID string
12752
+ syusrex_role_permissions_id_sygms: permissionId,
12753
+ syusrex_menu_id_syme: menuId,
12754
+ syusrex_isactive: true,
12755
+ _isUserAdded: true, // Mark as explicitly added by user
12756
+ _changeType: 'added' // Track the change type
12757
+ };
12758
+ // Add to entity mapping exceptions (check for duplicates first)
12759
+ this.entityMappings.update(mappings => {
12760
+ const updatedMappings = [...mappings];
12761
+ const mappingWithExceptions = updatedMappings[mappingIndex];
12762
+ if (!mappingWithExceptions.exceptions) {
12763
+ mappingWithExceptions.exceptions = [];
12764
+ }
12765
+ // Check if exception already exists to prevent duplicates
12766
+ const existingException = mappingWithExceptions.exceptions.find(ex => ex.syusrex_menu_id_syme === menuId &&
12767
+ ex.syusrex_role_permissions_id_sygms === permissionId);
12768
+ if (!existingException) {
12769
+ mappingWithExceptions.exceptions.push(exception);
12770
+ console.log('🎭 Role exception added (new):', exception);
12771
+ }
12772
+ else {
12773
+ // If exception exists but was removed, mark it as added again
12774
+ if (existingException._isUserRemoved) {
12775
+ existingException._isUserRemoved = false;
12776
+ existingException._isUserAdded = true;
12777
+ existingException._changeType = 'added';
12778
+ existingException.syusrex_isactive = true;
12779
+ console.log('🎭 Role exception reactivated:', existingException);
12780
+ }
12781
+ else {
12782
+ console.log('🎭 Role exception already exists, skipping duplicate:', existingException);
12783
+ }
12784
+ }
12785
+ return updatedMappings;
12786
+ });
12787
+ console.log('🎭 Role exception added:', exception);
12788
+ }
12789
+ /**
12790
+ * Remove role exception
12791
+ */
12792
+ removeRoleException(mappingIndex, menuId, permissionId) {
12793
+ this.entityMappings.update(mappings => {
12794
+ const updatedMappings = [...mappings];
12795
+ const mapping = updatedMappings[mappingIndex];
12796
+ if (mapping.exceptions) {
12797
+ // Instead of removing, mark as removed for tracking
12798
+ mapping.exceptions = mapping.exceptions.map((exception) => {
12799
+ if (exception.syusrex_menu_id_syme === menuId && exception.syusrex_role_permissions_id_sygms === permissionId) {
12800
+ return {
12801
+ ...exception,
12802
+ _isUserRemoved: true,
12803
+ _changeType: 'removed',
12804
+ syusrex_isactive: false
12805
+ };
12806
+ }
12807
+ return exception;
12808
+ });
12809
+ }
12810
+ return updatedMappings;
12811
+ });
12812
+ console.log('🎭 Role exception marked as removed:', { mappingIndex, menuId, permissionId });
12813
+ }
12814
+ /**
12815
+ * Collect only changed role exceptions from entity mappings
12816
+ */
12817
+ collectRoleExceptions() {
12818
+ const exceptions = [];
12819
+ const entityMappings = this.entityMappings();
12820
+ entityMappings.forEach((mapping, mappingIndex) => {
12821
+ // Get exceptions from the mapping
12822
+ const mappingWithExceptions = mapping;
12823
+ const mappingExceptions = mappingWithExceptions.exceptions || [];
12824
+ // Only include exceptions that have been explicitly changed by the user
12825
+ mappingExceptions.forEach((exception) => {
12826
+ // Check if this exception was explicitly added or removed by the user
12827
+ if (exception._isUserAdded || exception._isUserRemoved) {
12828
+ // Ensure role ID is direct string, not object
12829
+ const roleId = mapping.syenm_role_id_syusrol?._id ?? '';
12830
+ // Create a unique key for this exception to prevent duplicates
12831
+ const exceptionKey = `${mapping._id || `temp_${mappingIndex}`}_${roleId}_${exception.syusrex_role_permissions_id_sygms}_${exception.syusrex_menu_id_syme}`;
12832
+ // Check if this exception already exists in the collection
12833
+ const existingException = exceptions.find(ex => ex.syusrex_user_entity_mapping_id_syenm === (mapping._id || `temp_${mappingIndex}`) &&
12834
+ ex.syusrex_role_id_syusrol === roleId &&
12835
+ ex.syusrex_role_permissions_id_sygms === exception.syusrex_role_permissions_id_sygms &&
12836
+ ex.syusrex_menu_id_syme === exception.syusrex_menu_id_syme);
12837
+ if (!existingException) {
12838
+ exceptions.push({
12839
+ syusrex_user_entity_mapping_id_syenm: mapping._id || `temp_${mappingIndex}`,
12840
+ syusrex_role_id_syusrol: roleId,
12841
+ syusrex_role_permissions_id_sygms: exception.syusrex_role_permissions_id_sygms || '',
12842
+ syusrex_menu_id_syme: exception.syusrex_menu_id_syme || '',
12843
+ syusrex_isactive: exception.syusrex_isactive || false,
12844
+ _changeType: exception._changeType || 'unknown'
12845
+ });
12846
+ }
12847
+ else {
12848
+ console.log('🎭 Duplicate exception prevented:', exceptionKey);
12849
+ }
12850
+ }
12851
+ });
12852
+ });
12853
+ console.log('🎭 Collected changed role exceptions:', exceptions);
12854
+ return exceptions;
12855
+ }
12856
+ /**
12857
+ * Check if permission is selected for a menu
12858
+ */
12859
+ isPermissionSelected(menuId, permissionId) {
12860
+ const mappingIndex = this.getCurrentMappingIndex();
12861
+ if (mappingIndex === null)
12862
+ return false;
12863
+ return this.isPermissionInRole(permissionId, mappingIndex, menuId);
12864
+ }
12264
12865
  /**
12265
12866
  * Handle permission checkbox change (read-only in this context)
12266
12867
  */
@@ -12272,14 +12873,21 @@ class CideCoreUserCreateComponent {
12272
12873
  * Check if a menu has child menus with permissions
12273
12874
  */
12274
12875
  hasChildMenusWithPermissions(menuId) {
12275
- const rolePermissions = this.selectedRolePermissions();
12276
- const childMenus = rolePermissions.filter(menu => menu.syme_parent_id_syme === menuId);
12277
- return childMenus.some(childMenu => {
12278
- if (childMenu.permissions && childMenu.permissions.some((p) => p.isSelected)) {
12279
- return true;
12280
- }
12281
- // Recursively check grandchildren
12282
- return this.hasChildMenusWithPermissions(childMenu._id);
12876
+ // For simplified approach, we don't need to check child menus
12877
+ // Just return false as we're not using hierarchical permission checking
12878
+ return false;
12879
+ }
12880
+ /**
12881
+ * Update menu rights grid data to force refresh
12882
+ */
12883
+ updateMenuRightsGridData(mappingIndex) {
12884
+ const menuRights = this.getMenuRightsForMapping(mappingIndex);
12885
+ console.log('🔄 Updating menu rights grid data:', menuRights);
12886
+ // Force update the grid configuration
12887
+ this.menuRightsMap.update(map => {
12888
+ const newMap = { ...map };
12889
+ newMap[mappingIndex.toString()] = menuRights;
12890
+ return newMap;
12283
12891
  });
12284
12892
  }
12285
12893
  /**
@@ -12287,11 +12895,13 @@ class CideCoreUserCreateComponent {
12287
12895
  */
12288
12896
  getMenuRightsGridConfig(mappingIndex) {
12289
12897
  const menuRights = this.getMenuRightsForMapping(mappingIndex);
12898
+ console.log(`🔍 Grid config for mapping ${mappingIndex}:`);
12899
+ console.log(`📊 Menu rights count:`, menuRights.length);
12900
+ console.log(`📋 Menu rights data:`, menuRights);
12290
12901
  return {
12291
12902
  id: `menu-rights-grid-${mappingIndex}`,
12292
- title: 'Menu Rights & Permissions',
12293
- subtitle: 'Manage permissions for this entity-role mapping',
12294
- fullHeight: true,
12903
+ title: '',
12904
+ subtitle: '',
12295
12905
  columns: [
12296
12906
  {
12297
12907
  key: 'details',
@@ -12312,17 +12922,40 @@ class CideCoreUserCreateComponent {
12312
12922
  renderer: 'menuTypeRenderer'
12313
12923
  },
12314
12924
  {
12315
- key: 'permissions',
12925
+ key: 'syme_path',
12926
+ header: 'Path',
12927
+ type: 'text',
12928
+ width: '200px',
12929
+ truncate: true,
12930
+ align: 'left'
12931
+ },
12932
+ {
12933
+ key: 'syme_isactive',
12934
+ header: 'Status',
12935
+ type: 'status',
12936
+ width: '100px',
12937
+ truncate: false,
12938
+ align: 'center',
12939
+ statusConfig: {
12940
+ activeValue: true,
12941
+ activeLabel: 'Active',
12942
+ inactiveLabel: 'Inactive',
12943
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
12944
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
12945
+ }
12946
+ },
12947
+ {
12948
+ key: 'syme_permissions_id_sygms',
12316
12949
  header: 'Permissions',
12317
12950
  type: 'custom',
12318
- width: '300px',
12319
- truncate: false,
12951
+ width: '200px',
12952
+ truncate: true,
12320
12953
  align: 'left',
12321
12954
  renderer: 'permissionsRenderer'
12322
12955
  }
12323
12956
  ],
12324
12957
  data: menuRights,
12325
- trackBy: 'menu_id',
12958
+ trackBy: '_id',
12326
12959
  pagination: {
12327
12960
  enabled: false,
12328
12961
  pageSize: 10,
@@ -12334,37 +12967,43 @@ class CideCoreUserCreateComponent {
12334
12967
  search: {
12335
12968
  enabled: true,
12336
12969
  placeholder: 'Search menu items...',
12337
- searchableColumns: ['menu_name', 'menu_code'],
12970
+ searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
12338
12971
  debounceMs: 300
12339
12972
  },
12340
12973
  loading: {
12341
- useDefer: false,
12974
+ useDefer: true,
12342
12975
  skeletonRows: 5,
12343
12976
  showOverlay: false
12344
12977
  },
12345
12978
  scroll: {
12346
12979
  enabled: true,
12347
- maxHeight: '400px',
12348
- minHeight: '200px',
12980
+ maxHeight: '',
12981
+ minHeight: '',
12349
12982
  stickyHeader: true,
12350
12983
  virtualScroll: false,
12351
- rowHeight: 25
12984
+ rowHeight: 50
12352
12985
  },
12353
12986
  dragDrop: {
12354
- enabled: false,
12355
- orderField: '',
12356
- dragClass: '',
12357
- dropClass: ''
12987
+ enabled: true,
12988
+ orderField: 'syme_order_by',
12989
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
12990
+ dropClass: 'tw-bg-green-50'
12358
12991
  },
12359
12992
  responsive: true,
12360
12993
  striped: false,
12361
12994
  bordered: true,
12362
12995
  compact: false,
12363
12996
  tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
12997
+ onRefresh: 'onMenuItemRefresh',
12998
+ onRowReorder: 'onRowReorder',
12364
12999
  tree: {
12365
13000
  enabled: true,
12366
- primaryKey: 'menu_id',
12367
- foreignKey: 'parent_menu_id'
13001
+ primaryKey: '_id',
13002
+ foreignKey: 'syme_id_syme',
13003
+ childrenKey: 'children',
13004
+ levelKey: 'level',
13005
+ expandedKey: 'isExpanded',
13006
+ hasChildrenKey: 'hasChildren'
12368
13007
  }
12369
13008
  };
12370
13009
  }
@@ -12375,7 +13014,7 @@ class CideCoreUserCreateComponent {
12375
13014
  return {
12376
13015
  menuDetailsRenderer: this.menuDetailsRendererTemplate(),
12377
13016
  menuTypeRenderer: this.menuTypeRendererTemplate(),
12378
- permissionsRenderer: this.menuRightsPermissionsRendererTemplate()
13017
+ permissionsRenderer: this.permissionsRendererTemplate()
12379
13018
  };
12380
13019
  }
12381
13020
  /**
@@ -12448,71 +13087,99 @@ class CideCoreUserCreateComponent {
12448
13087
  console.warn('Entity and Role must be selected before loading menu rights');
12449
13088
  return;
12450
13089
  }
12451
- // Simulate API call to get menu rights for entity-role combination
12452
- // In real implementation, this would call a service
12453
- const simulatedMenuRights = [
12454
- {
12455
- menu_id: 'user-management',
12456
- menu_name: 'User Management',
12457
- menu_code: 'USRMGT',
12458
- role_rights: ['create', 'read', 'update'],
12459
- exceptions: []
12460
- },
12461
- {
12462
- menu_id: 'entity-management',
12463
- menu_name: 'Entity Management',
12464
- menu_code: 'ENTMGT',
12465
- role_rights: ['read', 'update'],
12466
- exceptions: []
12467
- },
12468
- {
12469
- menu_id: 'role-management',
12470
- menu_name: 'Role Management',
12471
- menu_code: 'ROLMGT',
12472
- role_rights: ['read'],
12473
- exceptions: []
12474
- },
12475
- {
12476
- menu_id: 'reports',
12477
- menu_name: 'Reports',
12478
- menu_code: 'RPTS',
12479
- role_rights: ['read'],
12480
- exceptions: []
13090
+ console.log('🚀 Loading menu rights for mapping:', mappingIndex);
13091
+ this.loading.set(true);
13092
+ this.error.set(null);
13093
+ // Use actual API call to get menu list
13094
+ const requestBody = {
13095
+ pageIndex: 1,
13096
+ pageSize: 1000, // Get all menu items - increased to ensure we get all records
13097
+ total: 1000, // Set total to match pageSize to get all records
13098
+ sort: { order: 'asc', key: 'syme_order_by' }
13099
+ };
13100
+ console.log('📤 Request body for menu list:', requestBody);
13101
+ this.menuService.getMenuList(requestBody)
13102
+ .pipe(takeUntilDestroyed(this.destroyRef))
13103
+ .subscribe({
13104
+ next: (response) => {
13105
+ console.log('✅ Menu list loaded successfully:', response);
13106
+ console.log('📊 Total menu items received:', response?.data?.length || 0);
13107
+ console.log('📋 Menu items data:', response?.data);
13108
+ if (response?.success && response?.data) {
13109
+ // Use menu data directly without transformation
13110
+ const menuRights = response.data.map((menu) => {
13111
+ // Get only the permissions that are mapped to this menu
13112
+ const mappedPermissions = this.permissions().filter(permission => menu.syme_permissions_id_sygms?.includes(permission._id || ''));
13113
+ // Pre-compute permission values for template performance
13114
+ const permissionValues = {};
13115
+ if (menu.syme_permissions_id_sygms) {
13116
+ menu.syme_permissions_id_sygms.forEach(permissionId => {
13117
+ const permission = this.getPermissionById(permissionId);
13118
+ if (permission) {
13119
+ permissionValues[permissionId] = {
13120
+ checked: this.getFormControlValue(menu, permissionId),
13121
+ permission: permission
13122
+ };
13123
+ }
13124
+ });
13125
+ }
13126
+ return {
13127
+ ...menu,
13128
+ role_rights: mappedPermissions, // Use only mapped permissions
13129
+ exceptions: [],
13130
+ _permissionValues: permissionValues // Pre-computed values
13131
+ };
13132
+ });
13133
+ // Update menu rights map
13134
+ this.menuRightsMap.update(map => {
13135
+ const newMap = {
13136
+ ...map,
13137
+ [mappingIndex.toString()]: menuRights
13138
+ };
13139
+ console.log('🗺️ Updated menu rights map:', newMap);
13140
+ return newMap;
13141
+ });
13142
+ console.log('📊 Processed menu rights count:', menuRights.length);
13143
+ console.log('📋 Menu rights data:', menuRights);
13144
+ // Initialize entity mapping exceptions array if not exists
13145
+ this.entityMappings.update(mappings => {
13146
+ const updatedMappings = [...mappings];
13147
+ if (!updatedMappings[mappingIndex].exceptions) {
13148
+ updatedMappings[mappingIndex].exceptions = [];
13149
+ }
13150
+ return updatedMappings;
13151
+ });
13152
+ console.log('✅ Menu rights loaded for mapping', mappingIndex);
13153
+ // Force refresh the grid to show updated permission states
13154
+ setTimeout(() => {
13155
+ this.cdr.detectChanges();
13156
+ // Also update the grid configuration to ensure data refresh
13157
+ this.updateMenuRightsGridData(mappingIndex);
13158
+ }, 100);
13159
+ }
13160
+ else {
13161
+ console.warn('⚠️ No menu data received from API');
13162
+ this.error.set('No menu data received from server');
13163
+ }
13164
+ this.loading.set(false);
12481
13165
  },
12482
- {
12483
- menu_id: 'dashboard',
12484
- menu_name: 'Dashboard',
12485
- menu_code: 'DASH',
12486
- role_rights: ['read'],
12487
- exceptions: []
13166
+ error: (error) => {
13167
+ console.error('❌ Error loading menu rights:', error);
13168
+ this.error.set('Failed to load menu rights');
13169
+ this.loading.set(false);
12488
13170
  }
12489
- ];
12490
- // Update menu rights map
12491
- this.menuRightsMap.update(map => ({
12492
- ...map,
12493
- [mappingIndex.toString()]: simulatedMenuRights
12494
- }));
12495
- // Add form controls for menu rights
12496
- simulatedMenuRights.forEach((menuRight, j) => {
12497
- this.userMasterForm.addControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.create`, this.fb.control(menuRight.role_rights.includes('create')));
12498
- this.userMasterForm.addControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.read`, this.fb.control(menuRight.role_rights.includes('read')));
12499
- this.userMasterForm.addControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.update`, this.fb.control(menuRight.role_rights.includes('update')));
12500
- this.userMasterForm.addControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.delete`, this.fb.control(menuRight.role_rights.includes('delete')));
12501
13171
  });
12502
- console.log('Menu rights loaded for mapping', mappingIndex);
12503
13172
  }
12504
13173
  refreshMenuRights(mappingIndex) {
12505
13174
  this.clearMenuRightsForMapping(mappingIndex);
12506
13175
  this.loadMenuRights(mappingIndex);
12507
13176
  }
12508
13177
  clearMenuRightsForMapping(mappingIndex) {
12509
- const currentMenuRights = this.getMenuRightsForMapping(mappingIndex);
12510
- // Remove form controls for menu rights
12511
- currentMenuRights.forEach((_, j) => {
12512
- this.userMasterForm.removeControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.create`);
12513
- this.userMasterForm.removeControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.read`);
12514
- this.userMasterForm.removeControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.update`);
12515
- this.userMasterForm.removeControl(`core_entity_mapping.${mappingIndex}.menu_rights.${j}.delete`);
13178
+ // Clear exceptions from entity mapping
13179
+ this.entityMappings.update(mappings => {
13180
+ const updatedMappings = [...mappings];
13181
+ updatedMappings[mappingIndex].exceptions = [];
13182
+ return updatedMappings;
12516
13183
  });
12517
13184
  // Clear from menu rights map
12518
13185
  this.menuRightsMap.update(map => {
@@ -12521,6 +13188,63 @@ class CideCoreUserCreateComponent {
12521
13188
  return updatedMap;
12522
13189
  });
12523
13190
  }
13191
+ /**
13192
+ * Load user rights type ID from general master types
13193
+ */
13194
+ loadUserRightsTypeId() {
13195
+ this.generalMasterTypeService.getTypeList({
13196
+ sygmt_code: "user_rights"
13197
+ })
13198
+ .pipe(takeUntilDestroyed(this.destroyRef))
13199
+ .subscribe({
13200
+ next: (response) => {
13201
+ if (response?.success && response.data) {
13202
+ const userRightsType = response.data.find(type => type.sygmt_code === 'user_rights' || type.sygmt_title?.toLowerCase().includes('user_rights'));
13203
+ if (userRightsType) {
13204
+ this.userRightsTypeId.set(userRightsType._id || null);
13205
+ this.loadPermissions();
13206
+ }
13207
+ else {
13208
+ this.error.set('User rights type not found in general master types');
13209
+ }
13210
+ }
13211
+ },
13212
+ error: (err) => {
13213
+ this.error.set('Failed to load user rights type');
13214
+ }
13215
+ });
13216
+ }
13217
+ /**
13218
+ * Load permissions from general master
13219
+ */
13220
+ loadPermissions() {
13221
+ const typeId = this.userRightsTypeId();
13222
+ if (!typeId) {
13223
+ this.error.set('User rights type not found. Please ensure the "user_rights" type exists in general master types.');
13224
+ return;
13225
+ }
13226
+ const payload = { sygms_id_sygmt: typeId };
13227
+ this.CideCoreGeneralMasterService.getMasterList(payload)
13228
+ .pipe(takeUntilDestroyed(this.destroyRef))
13229
+ .subscribe({
13230
+ next: (response) => {
13231
+ if (response?.success && response.data) {
13232
+ this.permissions.set(response.data);
13233
+ if (this.error()?.includes('permissions')) {
13234
+ this.error.set(null);
13235
+ }
13236
+ }
13237
+ else {
13238
+ this.permissions.set([]);
13239
+ this.error.set('No permissions found. Please ensure permissions are configured in general master.');
13240
+ }
13241
+ },
13242
+ error: (err) => {
13243
+ this.permissions.set([]);
13244
+ this.error.set('Failed to load permissions from general master. Please check your configuration.');
13245
+ }
13246
+ });
13247
+ }
12524
13248
  hasRoleRight(menuRight, permission) {
12525
13249
  return menuRight.role_rights.includes(permission);
12526
13250
  }
@@ -12658,6 +13382,59 @@ class CideCoreUserCreateComponent {
12658
13382
  uploadType: 'user_profile_photo',
12659
13383
  };
12660
13384
  }
13385
+ /**
13386
+ * Get upload data for document files with group ID
13387
+ */
13388
+ getDocumentUploadData(documentIndex) {
13389
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
13390
+ const photoGroupId = documentFormGroup?.get('syusd_photo_group_id_cyfm')?.value;
13391
+ const documentType = documentFormGroup?.get('syusd_document_type_id_sygms')?.value;
13392
+ const documentNumber = documentFormGroup?.get('syusd_doc_number')?.value;
13393
+ // Get document type name for better tagging
13394
+ const documentTypeName = this.documentTypeOptions().find(opt => opt._id === documentType)?.sygms_title || 'Document';
13395
+ return {
13396
+ altText: `${documentTypeName} - ${documentNumber || 'Document'}`,
13397
+ userId: this.appState.getCurrentUser()?._id || '',
13398
+ groupId: photoGroupId, // Use photo group ID or generate one
13399
+ permissions: ['read', 'write'],
13400
+ tags: ['user', 'document', documentTypeName.toLowerCase(), 'file'],
13401
+ uploadType: 'user_document',
13402
+ documentIndex: documentIndex,
13403
+ documentType: documentType,
13404
+ documentNumber: documentNumber
13405
+ };
13406
+ }
13407
+ /**
13408
+ * Handle document upload success
13409
+ * For multiple file upload, uploadResponse is the group ID
13410
+ */
13411
+ onDocumentUploadSuccess(groupId, documentIndex) {
13412
+ console.log(`📎 Document upload success for document ${documentIndex} with group ID:`, groupId);
13413
+ // Update the photo group ID in the form
13414
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
13415
+ if (documentFormGroup && groupId) {
13416
+ documentFormGroup.get('syusd_photo_group_id_cyfm')?.setValue(groupId);
13417
+ console.log(`📎 Updated photo group ID for document ${documentIndex}:`, groupId);
13418
+ }
13419
+ // For multiple file upload, we don't track individual files here
13420
+ // The files are managed by the group ID on the server
13421
+ // Clear any existing file tracking since we now use group ID
13422
+ documentFormGroup._uploadedFiles = [];
13423
+ }
13424
+ /**
13425
+ * Handle document upload error
13426
+ */
13427
+ onDocumentUploadError(error, documentIndex) {
13428
+ console.error(`❌ Document upload error for document ${documentIndex}:`, error);
13429
+ this.error.set(`Failed to upload document file: ${error?.message || 'Unknown error'}`);
13430
+ }
13431
+ /**
13432
+ * Handle document upload progress
13433
+ */
13434
+ onDocumentUploadProgress(progress, documentIndex) {
13435
+ console.log(`📊 Document upload progress for document ${documentIndex}: ${progress}%`);
13436
+ // You can add progress indication here if needed
13437
+ }
12661
13438
  /**
12662
13439
  * Load profile photo preview for existing photos
12663
13440
  */
@@ -12751,6 +13528,11 @@ class CideCoreUserCreateComponent {
12751
13528
  this.documents.update(docs => [...docs, newDocumentGroup.value]);
12752
13529
  }
12753
13530
  removeDocument(index) {
13531
+ // Clean up uploaded files for this document
13532
+ const documentFormGroup = this.documentsFormArray.at(index);
13533
+ if (documentFormGroup) {
13534
+ documentFormGroup._uploadedFiles = [];
13535
+ }
12754
13536
  // Remove the document from the FormArray
12755
13537
  this.documentsFormArray.removeAt(index);
12756
13538
  // Update the documents signal to keep UI in sync
@@ -12797,12 +13579,14 @@ class CideCoreUserCreateComponent {
12797
13579
  }
12798
13580
  if (this.userMasterForm.valid) {
12799
13581
  this.loading.set(true);
12800
- // Prepare form data with entity mappings and menu rights
12801
- const { core_entity_mapping, menu_rights, core_user_contact_addresses, core_user_documents, core_user_family_details, ...auth_user_mst } = this.userMasterForm.value;
13582
+ // Prepare form data with entity mappings and exceptions
13583
+ const { core_entity_mapping, core_user_contact_addresses, core_user_documents, core_user_family_details, ...auth_user_mst } = this.userMasterForm.value;
13584
+ // Collect exceptions from all entity mappings
13585
+ const core_user_role_exceptions = this.collectRoleExceptions();
12802
13586
  const formData = {
12803
13587
  auth_user_mst: auth_user_mst,
12804
13588
  core_entity_mapping: core_entity_mapping || [],
12805
- menu_rights: this.menuRightsMap() || {},
13589
+ core_user_role_exceptions: core_user_role_exceptions,
12806
13590
  core_user_contact_addresses: core_user_contact_addresses || [],
12807
13591
  core_user_documents: core_user_documents || [],
12808
13592
  core_user_family_details: core_user_family_details || [],
@@ -12826,7 +13610,7 @@ class CideCoreUserCreateComponent {
12826
13610
  console.log('🔐 Encrypting password for edit mode...');
12827
13611
  const originalPassword = dataWithPassword.user_password;
12828
13612
  dataWithPassword.user_password = customEncrypt(dataWithPassword.user_password);
12829
- console.log('✅ Password encrypted for edit mode:', { originalLength: originalPassword.length, encryptedLength: dataWithPassword.user_password.length });
13613
+ console.log('✅ Password encrypted for edit mode:', { originalLength: originalPassword, encryptedLength: customDecrypt(dataWithPassword.user_password), dataWithPassword: dataWithPassword.user_password });
12830
13614
  }
12831
13615
  formData.auth_user_mst = dataWithPassword;
12832
13616
  }
@@ -12838,15 +13622,12 @@ class CideCoreUserCreateComponent {
12838
13622
  console.log('🔐 Encrypting password for create mode...');
12839
13623
  const originalPassword = dataWithPassword.user_password;
12840
13624
  dataWithPassword.user_password = customEncrypt(dataWithPassword.user_password);
12841
- console.log('✅ Password encrypted for create mode:', { originalLength: originalPassword.length, encryptedLength: dataWithPassword.user_password.length });
13625
+ console.log('✅ Password encrypted for create mode:', { originalLength: originalPassword, encryptedLength: dataWithPassword.user_password.length });
12842
13626
  }
12843
13627
  formData.auth_user_mst = dataWithPassword;
12844
13628
  }
12845
13629
  // Log final form data being sent (without password for security)
12846
13630
  const logData = { ...formData };
12847
- if (logData.auth_user_mst.user_password) {
12848
- logData.auth_user_mst.user_password = '***ENCRYPTED***';
12849
- }
12850
13631
  console.log('📤 Sending form data to server:', logData);
12851
13632
  // Use the service to save user master
12852
13633
  this.userMasterService.saveUpdateUserMaster(logData)
@@ -12854,14 +13635,19 @@ class CideCoreUserCreateComponent {
12854
13635
  next: (response) => {
12855
13636
  console.log('✅ User master saved successfully:', response);
12856
13637
  this.loading.set(false);
13638
+ this.error.set(null); // Clear any previous errors
12857
13639
  if (this.isEditMode()) {
12858
- // In edit mode, show success message and optionally navigate back
13640
+ // In edit mode, show success message
13641
+ this.success.set('User updated successfully! All changes have been saved.');
12859
13642
  console.log('User updated successfully');
12860
- // Optionally navigate back to user list
12861
- // this.goBackToUserList();
13643
+ // Auto-hide success message after 5 seconds
13644
+ setTimeout(() => this.success.set(null), 5000);
12862
13645
  }
12863
13646
  else {
12864
- // In create mode, reset form for new user
13647
+ // In create mode, show success message and reset form for new user
13648
+ this.success.set('User created successfully! You can now create another user.');
13649
+ // Auto-hide success message after 5 seconds
13650
+ setTimeout(() => this.success.set(null), 5000);
12865
13651
  this.resetForm();
12866
13652
  }
12867
13653
  },
@@ -13326,6 +14112,37 @@ class CideCoreUserCreateComponent {
13326
14112
  }
13327
14113
  });
13328
14114
  }
14115
+ /**
14116
+ * Load menu options from API
14117
+ */
14118
+ loadMenuOptions() {
14119
+ const requestBody = {
14120
+ pageIndex: 0,
14121
+ pageSize: 1000, // Load all menus
14122
+ total: 0,
14123
+ query: '',
14124
+ sort: {
14125
+ order: 'asc',
14126
+ key: 'syme_order_by'
14127
+ }
14128
+ };
14129
+ this.menuService.getMenuList(requestBody).subscribe({
14130
+ next: (response) => {
14131
+ if (response?.success) {
14132
+ console.log('🎭 Menu options loaded:', response.data);
14133
+ this.menuOptions.set(response.data || []);
14134
+ }
14135
+ else {
14136
+ console.error('❌ Failed to load menu options:', response);
14137
+ this.menuOptions.set([]);
14138
+ }
14139
+ },
14140
+ error: (error) => {
14141
+ console.error('❌ Error loading menu options:', error);
14142
+ this.menuOptions.set([]);
14143
+ }
14144
+ });
14145
+ }
13329
14146
  /**
13330
14147
  * Load dropdown data for existing addresses in edit mode
13331
14148
  */
@@ -13343,7 +14160,7 @@ class CideCoreUserCreateComponent {
13343
14160
  });
13344
14161
  }
13345
14162
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreUserCreateComponent, isStandalone: true, selector: "cide-core-user-create", viewQueries: [{ propertyName: "menuDetailsRendererTemplate", first: true, predicate: ["menuDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "permissionsCheckboxRendererTemplate", first: true, predicate: ["permissionsCheckboxRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuTypeRendererTemplate", first: true, predicate: ["menuTypeRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuRightsPermissionsRendererTemplate", first: true, predicate: ["menuRightsPermissionsRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \n ENTERPRISE USER MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full tw-p-3\">\n <form class=\"tw-max-w-7xl tw-mx-auto tw-bg-transparent\" [formGroup]=\"userMasterForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- User Context Header -->\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-md tw-p-2 tw-mb-3 tw-shadow-sm\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-flex-wrap tw-gap-2\">\n <!-- User Basic Info Display -->\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-flex-wrap\">\n <!-- Profile Photo Preview -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div\n class=\"tw-w-8 tw-h-8 tw-rounded-full tw-bg-blue-100 tw-border tw-border-blue-200 tw-flex tw-items-center tw-justify-center tw-overflow-hidden\">\n @if (userMasterForm.get('user_photo_id_cyfm')?.value) {\n <img \n cideEleFileImage \n [fileId]=\"userMasterForm.get('user_photo_id_cyfm')?.value\" \n [altText]=\"'Profile Photo'\"\n class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <cide-ele-icon \n name=\"person\" \n class=\"tw-w-5 tw-h-5 tw-text-blue-600\">\n </cide-ele-icon>\n }\n </div>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-xs tw-font-medium tw-text-blue-900\">\n {{ getUserFullName() || 'New User' }}\n </span>\n <span class=\"tw-text-xs tw-text-blue-600\">\n {{ getUserUsername() || 'Username not set' }}\n </span>\n </div>\n </div>\n\n <!-- Contact Info -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">email</cide-ele-icon>\n <span>{{ getUserEmail() || 'Email not set' }}</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">phone</cide-ele-icon>\n <span>{{ getUserMobile() || 'Mobile not set' }}</span>\n </div>\n </div>\n\n <!-- Active Status -->\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (getUserActiveStatus()) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-700\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">check_circle</cide-ele-icon>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-700\">\n <cide-ele-icon variant=\"red\" size=\"xs\" class=\"tw-mr-1\">cancel</cide-ele-icon>\n Inactive\n </span>\n }\n </div>\n </div>\n\n <!-- Entity Info -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"blue\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-font-medium\">{{ getDefaultEntityName() }}</span>\n </div>\n } @else {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-500\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-italic\">No entity</span>\n </div>\n }\n\n <span class=\"tw-text-xs tw-text-gray-600 tw-px-2 tw-py-1 tw-bg-gray-100 tw-rounded\">\n {{ getEntityMappingCount() }} mapping(s)\n </span>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-p-0 tw-mb-2 tw-border-b tw-border-gray-200\">\n <cide-ele-tab [tabs]=\"userTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- User Basic Information Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n\n <!-- Top Section: Form Fields on Left, Profile Photo on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-6 tw-mb-6\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-6\">\n <!-- Name Fields - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-input id=\"user_firstname\" label=\"First Name *\" formControlName=\"user_firstname\"\n placeholder=\"Enter first name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_middlename\" label=\"Middle Name\" formControlName=\"user_middlename\"\n placeholder=\"Enter middle name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_lastname\" label=\"Last Name *\" formControlName=\"user_lastname\"\n placeholder=\"Enter last name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_fullname\" label=\"Full Name * (Auto-generated)\" formControlName=\"user_fullname\"\n placeholder=\"Auto-generated from name fields or enter manually\" [maxlength]=\"62\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Contact Information - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\n <cide-ele-input id=\"user_username\" label=\"Username *\" formControlName=\"user_username\"\n placeholder=\"Enter unique username\" [maxlength]=\"20\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_emailid\" label=\"Email ID *\" formControlName=\"user_emailid\" type=\"email\"\n placeholder=\"Enter valid email address\" [maxlength]=\"320\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_mobileno\" label=\"Mobile Number *\" formControlName=\"user_mobileno\" type=\"tel\"\n placeholder=\"Enter mobile number\" [maxlength]=\"15\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Profile Photo Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-p-0\">\n <cide-ele-file-input \n id=\"user_photo_id_cyfm\" \n formControlName=\"user_photo_id_cyfm\"\n accept=\"image/*\"\n [showPreview]=\"true\"\n [previewBoxMode]=\"true\"\n [showFileName]=\"false\"\n previewWidth=\"180px\"\n previewHeight=\"120px\"\n placeholderText=\"Upload Photo\"\n placeholderIcon=\"cloud_upload\"\n [autoUpload]=\"true\"\n [uploadData]=\"getProfilePhotoUploadData()\"\n (uploadSuccess)=\"onProfilePhotoUploadSuccess($event)\"\n (uploadError)=\"onProfilePhotoUploadError($event)\"\n (uploadProgressChange)=\"onProfilePhotoUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n\n\n\n <!-- Status Control -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-4\">\n <div class=\"tw-p-4 tw-bg-blue-50 tw-border tw-border-blue-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200 hover:tw-bg-blue-75\">\n <cide-ele-input type=\"checkbox\" label=\"Active User Status\" formControlName=\"user_isactive\"\n class=\"tw-h-5 tw-accent-blue-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-font-semibold tw-text-gray-700 tw-text-base\"></span>\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">Enable this user account for system\n access and operations</span>\n </label>\n </div>\n </div>\n </div>\n }\n\n @case ('auth') {\n <!-- Authentication Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <!-- Password Fields -->\n @if (shouldShowPasswordFields()) {\n <div class=\"tw-mb-6\">\n <!-- Password Fields Header for Edit Mode -->\n @if (isEditMode()) {\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Update Password</h6>\n <button type=\"button\"\n class=\"tw-px-3 tw-py-1 tw-bg-gray-100 tw-text-gray-600 tw-border tw-border-gray-300 tw-rounded-md tw-text-xs tw-font-medium hover:tw-bg-gray-200 tw-transition-colors\"\n (click)=\"cancelPasswordUpdate()\">\n Cancel Password Update\n </button>\n </div>\n }\n\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 md:tw-grid-cols-1 tw-gap-6\">\n <cide-ele-input id=\"user_password\" [label]=\"getPasswordFieldLabel()\" formControlName=\"user_password\"\n type=\"password\" placeholder=\"Enter secure password (min 8 characters)\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_confirm_password\" [label]=\"getPasswordConfirmLabel()\"\n formControlName=\"user_confirm_password\" type=\"password\" placeholder=\"Confirm your password\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n }\n\n <!-- Password Update Option for Edit Mode -->\n @if (isEditMode() && !shouldShowPasswordFields()) {\n <div class=\"tw-mb-6\">\n <div class=\"tw-p-4 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-blue-800 tw-mb-2\">Password Update</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-mb-3\">Current password will be kept. Click below to change\n password.</p>\n\n @if (hasPasswordInput()) {\n <div\n class=\"tw-mb-3 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded tw-text-sm tw-text-yellow-700\">\n <cide-ele-icon variant=\"yellow\" size=\"xs\" class=\"tw-mr-1\">warning</cide-ele-icon>\n Password fields contain text. Click \"Change Password\" to manage existing input.\n </div>\n }\n\n <button type=\"button\"\n class=\"tw-px-4 tw-py-2 tw-bg-blue-100 tw-text-blue-700 tw-border tw-border-blue-300 tw-rounded-md tw-text-sm tw-font-medium hover:tw-bg-blue-200 tw-transition-colors\"\n (click)=\"triggerPasswordUpdate()\">\n @if (hasPasswordInput()) {\n Manage Password Fields\n } @else {\n Change Password\n }\n </button>\n </div>\n </div>\n }\n\n <!-- Password Options -->\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-6 tw-mb-6\">\n <div class=\"tw-p-4 tw-bg-yellow-50 tw-border tw-border-yellow-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-gap-2 tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200\">\n <cide-ele-input type=\"checkbox\" label=\"Force Password Change on Login\"\n formControlName=\"user_passwordchangeonlogin\" class=\"tw-h-5 tw-accent-yellow-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">User will be required to change\n password on next login</span>\n </label>\n </div>\n </div>\n\n </div>\n }\n\n @case ('roles') {\n <!-- Entity, Roles & Permissions Mapping Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n\n\n\n <!-- Important Note -->\n <div class=\"tw-bg-amber-50 tw-border tw-border-amber-200 tw-rounded-lg tw-p-4 tw-mb-6\">\n <div class=\"tw-flex tw-items-start tw-gap-3\">\n <cide-ele-icon variant=\"amber\" size=\"lg\">info</cide-ele-icon>\n <div class=\"tw-flex-1\">\n <h4 class=\"tw-text-sm tw-font-semibold tw-text-amber-800 tw-mb-1\">Entity-Role Based Access</h4>\n <p class=\"tw-text-sm tw-text-amber-700 tw-mb-2\">User access is completely managed through entity-role\n mappings below. At least one entity mapping is required for user access.</p>\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mt-2 tw-p-2 tw-bg-amber-100 tw-rounded\">\n <cide-ele-icon variant=\"amber\" size=\"sm\">star</cide-ele-icon>\n <span class=\"tw-text-sm tw-text-amber-800\">\n <strong>Default Entity:</strong> {{ getDefaultEntityName() }}\n </span>\n </div>\n } @else {\n <div class=\"tw-text-sm tw-text-amber-600 tw-mt-2 tw-italic\">\n \u26A0\uFE0F No default entity selected. Please set one entity as default.\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Entity-Role Mapping Section -->\n <div class=\"tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg tw-p-6 tw-mb-6\">\n <div class=\"tw-flex tw-text-center tw-justify-between tw-items-center tw-mb-4\">\n <div>\n <h4 class=\"tw-text-sm tw-text-left tw-font-semibold tw-text-blue-900 tw-mb-1\">Entity-Role Mapping</h4>\n <p class=\"tw-text-sm tw-text-blue-700\">Map user to entities with specific roles and permissions</p>\n </div>\n <div class=\"tw-flex tw-flex-col tw-items-end\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addEntityMapping()\" leftIcon=\"add\"\n [disabled]=\"isAllEntitiesMapped()\">\n Add Entity Mapping\n </button>\n \n @if (isAllEntitiesMapped()) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-md tw-max-w-xs\">\n <p class=\"tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"info\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All available entities are already mapped.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div formArrayName=\"core_entity_mapping\">\n @for (mapping of entityMappings(); track $index; let i = $index) {\n <div class=\"tw-bg-white tw-border tw-border-blue-200 tw-rounded-xl tw-mb-6 tw-overflow-hidden tw-shadow-sm\"\n [formGroupName]=\"i\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-blue-100 tw-px-6 tw-py-3 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h5 class=\"tw-m-0 tw-text-blue-800 tw-text-sm tw-font-semibold\">Entity Mapping {{ i + 1 }}</h5>\n @if (mapping.syenm_isdefault) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">star</cide-ele-icon>\n Default\n </span>\n }\n </div>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n\n <div class=\"tw-p-6\">\n <!-- Entity and Role Selection -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <div>\n <cide-ele-select label=\"Entity *\" [options]=\"getFilteredEntityOptions(i)\" formControlName=\"syenm_entity_id_syen\"\n valueKey=\"_id\" labelKey=\"syen_name\" placeholder=\"Select entity\" size=\"md\"\n (change)=\"onEntityChange(i, $event)\">\n </cide-ele-select>\n \n @if (isAllEntitiesSelected(i)) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-md\">\n <p class=\"tw-text-xs tw-text-yellow-700\">\n <cide-ele-icon variant=\"warning\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All entities are already mapped. Remove another mapping to add this one.\n </p>\n </div>\n }\n </div>\n <cide-ele-select label=\"Role for this Entity\" [options]=\"getRoleOptionsForEntity(i)\"\n formControlName=\"syenm_role_id_syusrol\" valueKey=\"_id\" labelKey=\"syusrol_role_name\" placeholder=\"Select role for this entity\" size=\"md\"\n (change)=\"onRoleChange(i, $event)\">\n </cide-ele-select>\n </div>\n\n <!-- Role Permissions Grid -->\n @if (selectedEntityIndex() === i && selectedRoleId()) {\n <div class=\"tw-mb-6 tw-border tw-border-gray-200 tw-rounded-lg tw-bg-gray-50\">\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-white tw-rounded-t-lg\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">security</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800 tw-m-0\">Role Permissions Preview</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">(Read-only view of selected role permissions)</span>\n </div>\n </div>\n \n <div class=\"tw-p-4\">\n @if (loading()) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-py-8\">\n <div class=\"tw-animate-spin tw-rounded-full tw-h-8 tw-w-8 tw-border-b-2 tw-border-blue-600\"></div>\n <span class=\"tw-ml-2 tw-text-gray-600\">Loading role permissions...</span>\n </div>\n } @else if (error()) {\n <div class=\"tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n } @else {\n <cide-ele-data-grid \n [config]=\"rolePermissionsGridConfig()\" \n [templateRenderers]=\"templateRenderers\"\n (gridEvent)=\"onRolePermissionsGridEvent($event)\"\n class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n }\n </div>\n </div>\n }\n\n <!-- Entity-Specific Details -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Department for this Entity\" [options]=\"getDepartmentOptionsForEntity(i)\"\n formControlName=\"syenm_department_id_sydept\" (change)=\"onDepartmentChange($event)\" valueKey=\"_id\" labelKey=\"sydept_name\" placeholder=\"Select department\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Designation for this Entity\" [options]=\"getDesignationOptionsForEntity(i)\" valueKey=\"_id\" labelKey=\"sydsg_name\"\n formControlName=\"syenm_designation_id_sydsg\" placeholder=\"Select designation\" size=\"md\">\n </cide-ele-select>\n </div>\n\n <!-- Active Period for Entity Mapping -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Active From *\" [id]=\"'syenm_activefrom['+i+']'\"\n formControlName=\"syenm_activefrom\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Active Until\" [id]=\"'syenm_activeupto['+i+']'\"\n formControlName=\"syenm_activeupto\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Mapping Settings -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6 tw-mb-6\">\n <div class=\"tw-p-3 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Default Entity\" formControlName=\"syenm_isdefault\"\n (change)=\"onDefaultEntityChange(i, $event)\" class=\"tw-h-5 tw-accent-green-500\" />\n <span class=\"tw-text-xs tw-text-green-600 tw-block tw-mt-1\">Set as user's default entity (only one\n allowed)</span>\n </div>\n\n <div class=\"tw-p-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Active Mapping\" formControlName=\"syenm_isactive\"\n class=\"tw-h-5 tw-accent-blue-500\" />\n <span class=\"tw-text-xs tw-text-blue-600 tw-block tw-mt-1\">Enable this entity mapping</span>\n </div>\n </div>\n\n <!-- Menu Rights Grid for this Entity-Role -->\n <div class=\"tw-border-t tw-border-gray-200 tw-pt-4\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-mb-4\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Menu Rights & Permissions</h6>\n <div class=\"tw-flex tw-gap-2\">\n <button cideEleButton variant=\"secondary\" size=\"sm\" type=\"button\" (click)=\"refreshMenuRights(i)\"\n leftIcon=\"refresh\">\n Refresh Rights\n </button>\n </div>\n </div>\n\n @if (getMenuRightsForMapping(i).length > 0) {\n <!-- Menu Rights Tree Grid -->\n <div class=\"tw-border tw-border-gray-200 tw-rounded-lg tw-bg-white\">\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-rounded-t-lg\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">security</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800 tw-m-0\">Menu Rights & Permissions</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">(Editable permissions for this entity-role mapping)</span>\n </div>\n </div>\n \n <div class=\"tw-p-4\">\n <cide-ele-data-grid \n [config]=\"getMenuRightsGridConfig(i)\" \n [templateRenderers]=\"getMenuRightsTemplateRenderers(i)\"\n (gridEvent)=\"onMenuRightsGridEvent($event, i)\"\n class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n </div>\n </div>\n\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg\">\n <div class=\"tw-text-gray-400 tw-mb-3\">\n <cide-ele-icon variant=\"gray\" size=\"lg\">menu</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-2\">No Menu Rights Available</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-mb-3 tw-text-center\">Select both entity and role to load\n menu rights for this mapping.</p>\n @if (mapping.syenm_entity_id_syen?._id && mapping.syenm_role_id_syusrol) {\n <button cideEleButton variant=\"primary\" size=\"sm\" type=\"button\" (click)=\"loadMenuRights(i)\"\n leftIcon=\"refresh\">\n Load Menu Rights\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (entityMappings().length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-bg-white tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-text-blue-400 tw-mb-3\">\n <cide-ele-icon variant=\"blue\" size=\"lg\">business</cide-ele-icon>\n </div>\n <h4 class=\"tw-text-sm tw-font-medium tw-text-blue-800 tw-mb-2\">No Entity Mappings</h4>\n <p class=\"tw-text-blue-600 tw-mb-4 tw-text-center\">Add entity mappings to assign specific roles and\n permissions for different entities.</p>\n <button class=\"tw-mx-auto\" cideEleButton variant=\"primary\" size=\"md\" type=\"button\"\n (click)=\"addEntityMapping()\" leftIcon=\"add\">\n Add First Entity Mapping\n </button>\n </div>\n }\n </div>\n\n\n </div>\n }\n\n @case ('addresses') {\n <!-- Contact Addresses Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end\">\n <div class=\"tw-flex tw-justify-between tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addContactAddress()\"\n leftIcon=\"add\">\n Add New Address\n </button>\n </div>\n </div>\n\n <div formArrayName=\"core_user_contact_addresses\">\n @for (address of contactAddresses(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Address {{ i + 1 }}</h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Address Type\" [options]=\"addressTypeOptions()\" id=\"sycad_address_type_id_sygms\"\n formControlName=\"sycad_address_type_id_sygms\" placeholder=\"Select address type\" size=\"md\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Contact Person Name\" formControlName=\"sycad_contact_person_name\"\n placeholder=\"Enter contact person name\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-6\">\n <cide-ele-textarea label=\"Complete Address\" formControlName=\"sycad_contact_address\"\n placeholder=\"Enter complete address with area, city, and landmarks\" [rows]=\"3\" size=\"md\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code & City -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select \n label=\"Postal Code\"\n [options]=\"addressPostalCodes()[i] || []\" \n formControlName=\"sycad_contact_pin_sypin\"\n placeholder=\"Select postal code\"\n [searchable]=\"true\"\n [loading]=\"addressPostalCodesLoading()[i] || false\"\n (searchChange)=\"onPostalCodeSearch($event, i)\"\n (change)=\"onPostalCodeSelection($event, i)\"\n size=\"md\">\n </cide-ele-select>\n \n <cide-ele-input \n label=\"City\" \n formControlName=\"sycad_contact_city_sypin\"\n placeholder=\"Enter city\"\n size=\"md\">\n </cide-ele-input>\n </div>\n \n <!-- State & Country -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"State\" \n formControlName=\"sycad_contact_state_sypin\"\n placeholder=\"Enter state\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Country\" \n [options]=\"addressCountries()[i] || []\" \n formControlName=\"sycad_contact_country_syctr\"\n placeholder=\"Select country\"\n valueKey=\"_id\"\n labelKey=\"syctr_country_iso_name\"\n [searchable]=\"true\"\n (searchChange)=\"onCountrySearch($event, i)\"\n [loading]=\"addressCountriesLoading()[i] || false\"\n size=\"md\">\n </cide-ele-select>\n </div>\n\n <!-- Phone Numbers -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"Primary Phone\" \n formControlName=\"sycad_contact_phone\"\n type=\"tel\"\n placeholder=\"Enter primary phone number\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Alternate Phone\" \n formControlName=\"sycad_contact_phone_alt\"\n type=\"tel\"\n placeholder=\"Enter alternate phone number\"\n size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Fax & Email -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"Fax Number\" \n formControlName=\"sycad_contact_fax\"\n placeholder=\"Enter fax number\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Primary Email\" \n formControlName=\"sycad_contact_email\"\n type=\"email\"\n placeholder=\"Enter primary email address\"\n size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Alternate Email -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-6\">\n <cide-ele-input \n label=\"Alternate Email\" \n formControlName=\"sycad_contact_email_alt\"\n type=\"email\"\n placeholder=\"Enter alternate email address\"\n size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('documents') {\n <!-- Documents Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addDocument()\" leftIcon=\"add\">\n Add Document\n </button>\n </div>\n\n <div formArrayName=\"core_user_documents\">\n @for (doc of documents(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Document {{ i + 1 }}</h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Document Type\" [options]=\"documentTypeOptions()\"\n formControlName=\"syusd_document_type_id_sygms\"\n placeholder=\"Select document type\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Document Number\" formControlName=\"syusd_doc_number\"\n placeholder=\"Enter document number\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Name as per Document\"\n formControlName=\"syusd_doc_name_as_per_doc\"\n placeholder=\"Enter name exactly as shown on document\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Photo Group\" [options]=\"photoGroupOptions()\"\n formControlName=\"syusd_photo_group_id_cyfm\"\n placeholder=\"Select photo group\" size=\"md\" valueKey=\"_id\" labelKey=\"cyfm_name\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Issue Date\" formControlName=\"syusd_doc_issue_date\"\n [id]=\"'syusd_doc_issue_date['+i+']'\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Expiry Date\" formControlName=\"syusd_doc_expiry_date\"\n [id]=\"'syusd_doc_expiry_date['+i+']'\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Document Verification Status\" [options]=\"documentVerificationStatusOptions()\"\n formControlName=\"syusd_doc_verification_status_id_sygms\"\n placeholder=\"Select verification status\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Document KYC Status\" [options]=\"documentKycStatusOptions()\"\n formControlName=\"syusd_doc_kyc_status_id_sygms\"\n placeholder=\"Select KYC status\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addFamilyDetail()\" leftIcon=\"add\">\n Add Family Member\n </button>\n </div>\n\n <div formArrayName=\"core_user_family_details\">\n @for (family of familyDetails(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Family Member {{ i + 1 }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeFamilyDetail(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Family Member Name\"\n formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Family Member User\"\n [options]=\"userOptions(i)\"\n formControlName=\"syfdl_family_member_id_user\"\n placeholder=\"Select family member user\" \n size=\"md\" \n valueKey=\"_id\" \n labelKey=\"user_fullname\"\n [searchable]=\"true\"\n [loading]=\"userSearchLoading()[i] || false\"\n (searchChange)=\"onUserSearchChange($event, i)\"\n (change)=\"onUserSelectionChange($event, i)\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\"\n placeholder=\"Select relationship\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\"\n placeholder=\"Select blood group\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Date of Birth\"\n formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"md\"\n [id]=\"'syfdl_family_member_dob['+i+']'\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Phone\"\n formControlName=\"syfdl_contact_phone\"\n type=\"tel\" placeholder=\"Enter contact phone\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\"\n type=\"email\" placeholder=\"Enter contact email\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Email ID\" formControlName=\"syfdl_contact_email_id\"\n type=\"email\" placeholder=\"Enter contact email ID\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\"\n type=\"tel\" placeholder=\"Enter contact number\" size=\"md\">\n </cide-ele-input>\n\n <div class=\"tw-flex tw-items-center tw-pt-6\">\n <cide-ele-input \n formControlName=\"syfdl_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Form Actions -->\n <div\n class=\"tw-flex tw-justify-end tw-gap-4 tw-py-2 tw-bg-white tw-border-t tw-border-gray-200 tw-sticky tw-bottom-0 tw-z-10\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || userMasterForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n Save User Master\n </button>\n </div>\n </form>\n</div>\n\n<!-- Template Renderers for Role Permissions Grid -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n @if (row.syme_type === 'module') {\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">folder</cide-ele-icon>\n } @else if (row.syme_type === 'section') {\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">folder_open</cide-ele-icon>\n } @else if (row.syme_type === 'menu') {\n <cide-ele-icon class=\"tw-text-purple-600 tw-w-4 tw-h-4\">menu</cide-ele-icon>\n } @else {\n <cide-ele-icon class=\"tw-text-gray-600 tw-w-4 tw-h-4\">description</cide-ele-icon>\n }\n </div>\n \n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.syme_title\">\n {{ row.syme_title || row.menu?.syme_title || row.menu?.syme_menu_name || 'Untitled' }}\n </div>\n <!-- Green pill indicator for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800 tw-whitespace-nowrap\">\n Assigned\n </span>\n }\n }\n </div>\n @if (row.permission?.sygms_name) {\n <div class=\"tw-text-xs tw-text-blue-500 tw-truncate\" \n [title]=\"row.permission?.sygms_name\">\n {{ row.permission?.sygms_name }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center\">\n @if (row.syme_type === 'module') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-blue-100 tw-text-blue-800\">\n Module\n </span>\n } @else if (row.syme_type === 'section') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Section\n </span>\n } @else if (row.syme_type === 'menu') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-purple-100 tw-text-purple-800\">\n Menu\n </span>\n } @else {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800\">\n {{ row.syme_type || 'Unknown' }}\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Checkbox Renderer Template -->\n<ng-template #permissionsCheckboxRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row.syme_type === 'menu' && row?.syme_permissions_id_sygms && row?.syme_permissions_id_sygms.length > 0) {\n @for (permissionId of row?.syme_permissions_id_sygms || []; track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"isPermissionSelected(row._id, permissionId)\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">\n {{ getPermissionById(permissionId)?.sygms_name || 'Unknown' }}\n </label>\n </div>\n </div>\n }\n } @else {\n <!-- Show green checkmark for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section' || row.syme_type === 'title') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-green-100 tw-rounded-full\">\n <cide-ele-icon \n class=\"tw-text-green-600\" \n size=\"xs\">\n check\n </cide-ele-icon>\n </div>\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Menu Rights Permissions Renderer Template -->\n<ng-template #menuRightsPermissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n <!-- Role Rights Display -->\n @if (row.role_rights && row.role_rights.length > 0) {\n <div class=\"tw-mb-2\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Role Rights:</div>\n <div class=\"tw-flex tw-flex-wrap tw-gap-1\">\n @for (right of row.role_rights; track $index) {\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-blue-100 tw-text-blue-800 tw-rounded\">\n {{ right }}\n </span>\n }\n </div>\n </div>\n }\n \n <!-- Individual Permission Controls -->\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-2 tw-w-full\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.create\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-green-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-green-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Create</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.read\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Read</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.update\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-yellow-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-yellow-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Update</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.delete\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-red-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-red-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Delete</label>\n </div>\n </div>\n \n <!-- Exception Indicator -->\n @if (row.hasException) {\n <div class=\"tw-mt-2\">\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-yellow-100 tw-text-yellow-800 tw-rounded\">\n Override\n </span>\n </div>\n } @else {\n <div class=\"tw-mt-2\">\n <span class=\"tw-text-xs tw-text-gray-400\">Default</span>\n </div>\n }\n </div>\n</ng-template>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { kind: "component", type: CideEleFileInputComponent, selector: "cide-ele-file-input", inputs: ["label", "accept", "multiple", "disabled", "required", "helperText", "errorText", "showPreview", "previewWidth", "previewHeight", "previewBoxMode", "showFileName", "placeholderText", "placeholderIcon", "autoUpload", "uploadData"], outputs: ["fileChange", "uploadSuccess", "uploadError", "uploadProgressChange"] }, { kind: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }] });
14163
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreUserCreateComponent, isStandalone: true, selector: "cide-core-user-create", viewQueries: [{ propertyName: "menuDetailsRendererTemplate", first: true, predicate: ["menuDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "permissionsCheckboxRendererTemplate", first: true, predicate: ["permissionsCheckboxRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuTypeRendererTemplate", first: true, predicate: ["menuTypeRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "menuRightsPermissionsRendererTemplate", first: true, predicate: ["menuRightsPermissionsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "permissionsRendererTemplate", first: true, predicate: ["permissionsRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \n ENTERPRISE USER MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full tw-p-1 tw-pt-2\">\n <form class=\"tw-max-w-7xl tw-mx-auto tw-bg-transparent\" [formGroup]=\"userMasterForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- Success/Error Messages -->\n @if (success()) {\n <div class=\"tw-mb-4 tw-p-4 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-md tw-shadow-sm\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"check_circle\" class=\"tw-text-green-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-green-800 tw-m-0\">Success</h3>\n <p class=\"tw-text-sm tw-text-green-700 tw-mt-1 tw-m-0\">{{ success() }}</p>\n </div>\n <button type=\"button\" (click)=\"success.set(null)\" class=\"tw-ml-auto tw-text-green-400 hover:tw-text-green-600\">\n <cide-ele-icon name=\"close\" class=\"tw-w-4 tw-h-4\"></cide-ele-icon>\n </button>\n </div>\n </div>\n }\n @if (error()) {\n <div class=\"tw-mb-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md tw-shadow-sm\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n <button type=\"button\" (click)=\"error.set(null)\" class=\"tw-ml-auto tw-text-red-400 hover:tw-text-red-600\">\n <cide-ele-icon name=\"close\" class=\"tw-w-4 tw-h-4\"></cide-ele-icon>\n </button>\n </div>\n </div>\n }\n\n <!-- User Context Header -->\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-md tw-p-1 tw-mb-2 tw-shadow-sm\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-flex-wrap tw-gap-2\">\n <!-- User Basic Info Display -->\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-flex-wrap\">\n <!-- Profile Photo Preview -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div\n class=\"tw-w-8 tw-h-8 tw-rounded-full tw-bg-blue-100 tw-border tw-border-blue-200 tw-flex tw-items-center tw-justify-center tw-overflow-hidden\">\n @if (userMasterForm.get('user_photo_id_cyfm')?.value) {\n <img cideEleFileImage [fileId]=\"userMasterForm.get('user_photo_id_cyfm')?.value\"\n [altText]=\"'Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <cide-ele-icon name=\"person\" class=\"tw-w-5 tw-h-5 tw-text-blue-600\">\n </cide-ele-icon>\n }\n </div>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-xs tw-font-medium tw-text-blue-900\">\n {{ getUserFullName() || 'New User' }}\n </span>\n <span class=\"tw-text-xs tw-text-blue-600\">\n {{ getUserUsername() || 'Username not set' }}\n </span>\n </div>\n </div>\n\n <!-- Contact Info -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">email</cide-ele-icon>\n <span>{{ getUserEmail() || 'Email not set' }}</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">phone</cide-ele-icon>\n <span>{{ getUserMobile() || 'Mobile not set' }}</span>\n </div>\n </div>\n\n <!-- Active Status -->\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (getUserActiveStatus()) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-700\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">check_circle</cide-ele-icon>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-700\">\n <cide-ele-icon variant=\"red\" size=\"xs\" class=\"tw-mr-1\">cancel</cide-ele-icon>\n Inactive\n </span>\n }\n </div>\n </div>\n\n <!-- Entity Info -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"blue\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-font-medium\">{{ getDefaultEntityName() }}</span>\n </div>\n } @else {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-500\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-italic\">No entity</span>\n </div>\n }\n\n <span class=\"tw-text-xs tw-text-gray-600 tw-px-2 tw-py-1 tw-bg-gray-100 tw-rounded\">\n {{ getEntityMappingCount() }} mapping(s)\n </span>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-p-0 tw-mb-2 tw-border-b tw-border-gray-200\">\n <cide-ele-tab [tabs]=\"userTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- User Basic Information Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n\n <!-- Top Section: Form Fields on Left, Profile Photo on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4 tw-mb-4\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-4\">\n <!-- Name Fields - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-input id=\"user_firstname\" label=\"First Name *\" formControlName=\"user_firstname\"\n placeholder=\"Enter first name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_middlename\" label=\"Middle Name\" formControlName=\"user_middlename\"\n placeholder=\"Enter middle name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_lastname\" label=\"Last Name *\" formControlName=\"user_lastname\"\n placeholder=\"Enter last name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_fullname\" label=\"Full Name * (Auto-generated)\" formControlName=\"user_fullname\"\n placeholder=\"Auto-generated from name fields or enter manually\" [maxlength]=\"62\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Contact Information - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\n <cide-ele-input id=\"user_username\" label=\"Username *\" formControlName=\"user_username\"\n placeholder=\"Enter unique username\" [maxlength]=\"20\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_emailid\" label=\"Email ID *\" formControlName=\"user_emailid\" type=\"email\"\n placeholder=\"Enter valid email address\" [maxlength]=\"320\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_mobileno\" label=\"Mobile Number *\" formControlName=\"user_mobileno\" type=\"tel\"\n placeholder=\"Enter mobile number\" [maxlength]=\"15\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Profile Photo Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-p-0\">\n <cide-ele-file-input id=\"user_photo_id_cyfm\" formControlName=\"user_photo_id_cyfm\" accept=\"image/*\"\n [showPreview]=\"true\" [previewBoxMode]=\"true\" [showFileName]=\"false\" previewWidth=\"180px\"\n previewHeight=\"120px\" placeholderText=\"Upload Photo\" placeholderIcon=\"cloud_upload\" [autoUpload]=\"true\"\n [uploadData]=\"getProfilePhotoUploadData()\" (uploadSuccess)=\"onProfilePhotoUploadSuccess($event)\"\n (uploadError)=\"onProfilePhotoUploadError($event)\"\n (uploadProgressChange)=\"onProfilePhotoUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n\n\n\n <!-- Status Control -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-2\">\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200 hover:tw-bg-blue-75\">\n <cide-ele-input type=\"checkbox\" label=\"Active User Status\" formControlName=\"user_isactive\"\n class=\"tw-h-5 tw-accent-blue-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-font-semibold tw-text-gray-700 tw-text-base\"></span>\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">Enable this user account for system\n access and operations</span>\n </label>\n </div>\n </div>\n </div>\n }\n\n @case ('auth') {\n <!-- Authentication Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <!-- Password Fields -->\n @if (shouldShowPasswordFields()) {\n <div class=\"tw-mb-4\">\n <!-- Password Fields Header for Edit Mode -->\n @if (isEditMode()) {\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Update Password</h6>\n <button type=\"button\"\n class=\"tw-px-3 tw-py-1 tw-bg-gray-100 tw-text-gray-600 tw-border tw-border-gray-300 tw-rounded-md tw-text-xs tw-font-medium hover:tw-bg-gray-200 tw-transition-colors\"\n (click)=\"cancelPasswordUpdate()\">\n Cancel Password Update\n </button>\n </div>\n }\n\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 md:tw-grid-cols-1 tw-gap-6\">\n <cide-ele-input id=\"user_password\" [label]=\"getPasswordFieldLabel()\" formControlName=\"user_password\"\n type=\"password\" placeholder=\"Enter secure password (min 8 characters)\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_confirm_password\" [label]=\"getPasswordConfirmLabel()\"\n formControlName=\"user_confirm_password\" type=\"password\" placeholder=\"Confirm your password\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n }\n\n <!-- Password Update Option for Edit Mode -->\n @if (isEditMode() && !shouldShowPasswordFields()) {\n <div class=\"tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-blue-800 tw-mb-2\">Password Update</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-mb-3\">Current password will be kept. Click below to change\n password.</p>\n\n @if (hasPasswordInput()) {\n <div\n class=\"tw-mb-3 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded tw-text-sm tw-text-yellow-700\">\n <cide-ele-icon variant=\"yellow\" size=\"xs\" class=\"tw-mr-1\">warning</cide-ele-icon>\n Password fields contain text. Click \"Change Password\" to manage existing input.\n </div>\n }\n\n <button type=\"button\"\n class=\"tw-px-4 tw-py-2 tw-bg-blue-100 tw-text-blue-700 tw-border tw-border-blue-300 tw-rounded-md tw-text-sm tw-font-medium hover:tw-bg-blue-200 tw-transition-colors\"\n (click)=\"triggerPasswordUpdate()\">\n @if (hasPasswordInput()) {\n Manage Password Fields\n } @else {\n Change Password\n }\n </button>\n </div>\n </div>\n }\n\n <!-- Password Options -->\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-4 tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-gap-2 tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200\">\n <cide-ele-input type=\"checkbox\" label=\"Force Password Change on Login\"\n formControlName=\"user_passwordchangeonlogin\" class=\"tw-h-5 tw-accent-yellow-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">User will be required to change\n password on next login</span>\n </label>\n </div>\n </div>\n\n </div>\n }\n\n @case ('roles') {\n <!-- Entity, Roles & Permissions Mapping Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n\n\n\n <!-- Important Note -->\n <div class=\"tw-bg-amber-50 tw-border tw-border-amber-200 tw-rounded-lg tw-p-2 tw-mb-4\">\n <div class=\"tw-flex tw-items-start tw-gap-3\">\n <cide-ele-icon variant=\"amber\" size=\"lg\">info</cide-ele-icon>\n <div class=\"tw-flex-1\">\n <h4 class=\"tw-text-sm tw-font-semibold tw-text-amber-800 tw-mb-1\">Entity-Role Based Access</h4>\n <p class=\"tw-text-sm tw-text-amber-700 tw-mb-2\">User access is completely managed through entity-role\n mappings below. At least one entity mapping is required for user access.</p>\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mt-2 tw-p-2 tw-bg-amber-100 tw-rounded\">\n <cide-ele-icon variant=\"amber\" size=\"sm\">star</cide-ele-icon>\n <span class=\"tw-text-sm tw-text-amber-800\">\n <strong>Default Entity:</strong> {{ getDefaultEntityName() }}\n </span>\n </div>\n } @else {\n <div class=\"tw-text-sm tw-text-amber-600 tw-mt-2 tw-italic\">\n \u26A0\uFE0F No default entity selected. Please set one entity as default.\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Entity-Role Mapping Section -->\n <div class=\"tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg tw-p-3 tw-mb-4\">\n <div class=\"tw-flex tw-text-center tw-justify-between tw-items-center tw-mb-4\">\n <div>\n <h4 class=\"tw-text-sm tw-text-left tw-font-semibold tw-text-blue-900 tw-mb-1\">Entity-Role Mapping</h4>\n <p class=\"tw-text-sm tw-text-blue-700\">Map user to entities with specific roles and permissions</p>\n </div>\n <div class=\"tw-flex tw-flex-col tw-items-end\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addEntityMapping()\"\n leftIcon=\"add\" [disabled]=\"isAllEntitiesMapped()\">\n Add Entity Mapping\n </button>\n\n @if (isAllEntitiesMapped()) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-md tw-max-w-xs\">\n <p class=\"tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"info\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All available entities are already mapped.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div formArrayName=\"core_entity_mapping\">\n @for (mapping of entityMappings(); track $index; let i = $index) {\n <div class=\"tw-bg-white tw-border tw-border-blue-200 tw-rounded-xl tw-mb-6 tw-overflow-hidden tw-shadow-sm\"\n [formGroupName]=\"i\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-blue-100 tw-px-6 tw-py-3 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h5 class=\"tw-m-0 tw-text-blue-800 tw-text-sm tw-font-semibold\">Entity Mapping {{ i + 1 }}</h5>\n @if (mapping.syenm_isdefault) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">star</cide-ele-icon>\n Default\n </span>\n }\n </div>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n\n <div>\n <!-- Entity and Role Selection -->\n <div class=\"tw-grid tw-px-3 tw-py-1 tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4 tw-mb-4\">\n <div>\n <cide-ele-select label=\"Entity *\" [options]=\"getFilteredEntityOptions(i)\"\n formControlName=\"syenm_entity_id_syen\" valueKey=\"_id\" labelKey=\"syen_name\"\n placeholder=\"Select entity\" size=\"md\" (change)=\"onEntityChange(i, $event)\">\n </cide-ele-select>\n\n @if (isAllEntitiesSelected(i)) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-md\">\n <p class=\"tw-text-xs tw-text-yellow-700\">\n <cide-ele-icon variant=\"warning\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All entities are already mapped. Remove another mapping to add this one.\n </p>\n </div>\n }\n </div>\n <cide-ele-select label=\"Role for this Entity\" [options]=\"getRoleOptionsForEntity(i)\"\n formControlName=\"syenm_role_id_syusrol\" valueKey=\"_id\" labelKey=\"syusrol_role_name\"\n placeholder=\"Select role for this entity\" size=\"md\" (change)=\"onRoleChange(i, $event)\">\n </cide-ele-select>\n </div>\n\n\n <!-- Entity-Specific Details and Active Period - All in One Row -->\n <div class=\"tw-grid tw-px-3 tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4 tw-mb-4\">\n <cide-ele-select label=\"Department for this Entity\" [options]=\"getDepartmentOptionsForEntity(i)\"\n formControlName=\"syenm_department_id_sydept\" (change)=\"onDepartmentChange($event)\" valueKey=\"_id\"\n labelKey=\"sydept_name\" placeholder=\"Select department\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Designation for this Entity\" [options]=\"getDesignationOptionsForEntity(i)\"\n valueKey=\"_id\" labelKey=\"sydsg_name\" formControlName=\"syenm_designation_id_sydsg\"\n placeholder=\"Select designation\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Active From *\" [id]=\"'syenm_activefrom['+i+']'\"\n formControlName=\"syenm_activefrom\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Active Until\" [id]=\"'syenm_activeupto['+i+']'\"\n formControlName=\"syenm_activeupto\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Mapping Settings -->\n <div class=\"tw-grid tw-px-3 tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Default Entity\" formControlName=\"syenm_isdefault\"\n (change)=\"onDefaultEntityChange(i, $event)\" class=\"tw-h-5 tw-accent-green-500\" />\n <span class=\"tw-text-xs tw-text-green-600 tw-block tw-mt-1\">Set as user's default entity (only one\n allowed)</span>\n </div>\n\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Active Mapping\" formControlName=\"syenm_isactive\"\n class=\"tw-h-5 tw-accent-blue-500\" />\n <span class=\"tw-text-xs tw-text-blue-600 tw-block tw-mt-1\">Enable this entity mapping</span>\n </div>\n </div>\n\n <!-- Menu Rights Grid for this Entity-Role -->\n <div class=\"tw-border-t tw-border-gray-200\">\n\n @if (getMenuRightsForMapping(i).length > 0) {\n <!-- Menu Rights Tree Grid -->\n\n <cide-ele-data-grid [config]=\"getMenuRightsGridConfig(i)\"\n [templateRenderers]=\"getMenuRightsTemplateRenderers(i)\"\n (gridEvent)=\"onMenuRightsGridEvent($event, i)\" class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg\">\n <div class=\"tw-text-gray-400 tw-mb-3\">\n <cide-ele-icon variant=\"gray\" size=\"lg\">menu</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-2\">No Menu Rights Available</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-mb-3 tw-text-center\">Select both entity and role to\n automatically load\n menu rights for this mapping.</p>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (entityMappings().length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-bg-white tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-text-blue-400 tw-mb-3\">\n <cide-ele-icon variant=\"blue\" size=\"lg\">business</cide-ele-icon>\n </div>\n <h4 class=\"tw-text-sm tw-font-medium tw-text-blue-800 tw-mb-2\">No Entity Mappings</h4>\n <p class=\"tw-text-blue-600 tw-mb-4 tw-text-center\">Add entity mappings to assign specific roles and\n permissions for different entities.</p>\n <button class=\"tw-mx-auto\" cideEleButton variant=\"primary\" size=\"md\" type=\"button\"\n (click)=\"addEntityMapping()\" leftIcon=\"add\">\n Add First Entity Mapping\n </button>\n </div>\n }\n </div>\n\n\n </div>\n }\n\n @case ('addresses') {\n <!-- Contact Addresses Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end\">\n <div class=\"tw-flex tw-justify-between tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addContactAddress()\"\n leftIcon=\"add\">\n Add New Address\n </button>\n </div>\n </div>\n\n <div formArrayName=\"core_user_contact_addresses\">\n @for (address of contactAddresses(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-4 tw-py-2 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <!-- Use address type as header instead of generic \"Address X\" -->\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">\n {{ getAddressTypeLabel(i) || ('Address ' + (i + 1)) }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-4\">\n <!-- Main Layout: Inputs on Left, Address Textarea on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n \n <!-- Left Side: Input Fields (3/4 width) -->\n <div class=\"lg:tw-col-span-3\">\n <!-- Row 1: Address Type, Contact Person -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Address Type\" [options]=\"addressTypeOptions()\" id=\"sycad_address_type_id_sygms\"\n formControlName=\"sycad_address_type_id_sygms\" placeholder=\"Select type\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\" (change)=\"onAddressTypeChange(i)\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Contact Person\" formControlName=\"sycad_contact_person_name\"\n placeholder=\"Enter contact person\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 2: Postal Code, City, State, Country -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-3\">\n <cide-ele-select label=\"Postal Code\" [options]=\"addressPostalCodes()[i] || []\"\n formControlName=\"sycad_contact_pin_sypin\" placeholder=\"Select postal code\" [searchable]=\"true\"\n [loading]=\"addressPostalCodesLoading()[i] || false\" (searchChange)=\"onPostalCodeSearch($event, i)\"\n (change)=\"onPostalCodeSelection($event, i)\" size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input label=\"City\" formControlName=\"sycad_contact_city_sypin\" placeholder=\"Enter city\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"State\" formControlName=\"sycad_contact_state_sypin\" placeholder=\"Enter state\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Country\" [options]=\"addressCountries()[i] || []\"\n formControlName=\"sycad_contact_country_syctr\" placeholder=\"Select country\" valueKey=\"_id\"\n labelKey=\"syctr_country_iso_name\" [searchable]=\"true\" (searchChange)=\"onCountrySearch($event, i)\"\n [loading]=\"addressCountriesLoading()[i] || false\" size=\"sm\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Right Side: Address Textarea (1/4 width, spans 2 rows) -->\n <div class=\"lg:tw-col-span-1 lg:tw-row-span-2 tw-flex tw-flex-col\">\n <cide-ele-textarea label=\"Complete Address\" formControlName=\"sycad_contact_address\"\n placeholder=\"Enter complete address with area, city, and landmarks\" [rows]=\"4\" size=\"sm\"\n class=\"tw-h-full\">\n </cide-ele-textarea>\n </div>\n </div>\n\n <!-- Contact Details: Primary Phone, Alt Phone, Fax, Primary Email in 4 columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Primary Phone\" formControlName=\"sycad_contact_phone\" type=\"tel\"\n placeholder=\"Primary phone\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Alternate Phone\" formControlName=\"sycad_contact_phone_alt\" type=\"tel\"\n placeholder=\"Alternate phone\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fax Number\" formControlName=\"sycad_contact_fax\" placeholder=\"Fax number\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Primary Email\" formControlName=\"sycad_contact_email\" type=\"email\"\n placeholder=\"Primary email\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Alternate Email in single row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-input label=\"Alternate Email\" formControlName=\"sycad_contact_email_alt\" type=\"email\"\n placeholder=\"Alternate email address\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('documents') {\n <!-- Documents Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addDocument()\" leftIcon=\"add\">\n Add Document\n </button>\n </div>\n\n <div formArrayName=\"core_user_documents\">\n @for (doc of documents(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-4 tw-py-2 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">\n {{ getDocumentTypeLabel(i) || ('Document ' + (i + 1)) }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-4\">\n <!-- Main Layout: Inputs on Left, File Upload on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-3 tw-gap-4\">\n \n <!-- Left Side: Document Information (2/3 width) -->\n <div class=\"lg:tw-col-span-2\">\n <!-- Row 1: Document Type, Document Number, Name as per Document -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Document Type\" [options]=\"documentTypeOptions()\"\n formControlName=\"syusd_document_type_id_sygms\" placeholder=\"Select type\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\" (change)=\"onDocumentTypeChange(i)\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Document Number\" formControlName=\"syusd_doc_number\"\n placeholder=\"Document number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Name as per Document\" formControlName=\"syusd_doc_name_as_per_doc\"\n placeholder=\"Name on document\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 2: Issue Date, Expiry Date, Photo Group -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Issue Date\" formControlName=\"syusd_doc_issue_date\"\n [id]=\"'syusd_doc_issue_date['+i+']'\" type=\"date\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Expiry Date\" formControlName=\"syusd_doc_expiry_date\"\n [id]=\"'syusd_doc_expiry_date['+i+']'\" type=\"date\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Photo Group\" [options]=\"photoGroupOptions()\"\n formControlName=\"syusd_photo_group_id_cyfm\" placeholder=\"Select group\" size=\"sm\" valueKey=\"_id\"\n labelKey=\"cyfm_name\">\n </cide-ele-select>\n </div>\n\n <!-- Row 3: Verification Status, KYC Status -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-select label=\"Verification Status\" [options]=\"documentVerificationStatusOptions()\"\n formControlName=\"syusd_doc_verification_status_id_sygms\" placeholder=\"Select status\"\n size=\"sm\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"KYC Status\" [options]=\"documentKycStatusOptions()\"\n formControlName=\"syusd_doc_kyc_status_id_sygms\" placeholder=\"Select KYC status\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Right Side: File Upload (1/3 width) -->\n <div class=\"lg:tw-col-span-1\">\n <div class=\"tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg tw-p-3 tw-h-full\">\n <h5 class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-mb-3 tw-m-0\">Document Files</h5>\n \n <!-- File Upload Input -->\n {{documentsFormArray.at(i).get('syusd_photo_group_id_cyfm')?.value}}\n <cide-ele-file-input\n [id]=\"'document-files-' + i\"\n [multiple]=\"true\"\n formControlName=\"syusd_photo_group_id_cyfm\"\n [accept]=\"'.pdf,.jpg,.jpeg,.png,.doc,.docx'\"\n [autoUpload]=\"true\"\n [uploadData]=\"getDocumentUploadData(i)\"\n (change)=\"onDocumentFilesSelected($event, i)\"\n (uploadSuccess)=\"onDocumentUploadSuccess($event, i)\"\n (uploadError)=\"onDocumentUploadError($event, i)\"\n (uploadProgressChange)=\"onDocumentUploadProgress($event, i)\"\n cideFloatingUploadTrigger\n class=\"tw-mb-3\"\n size=\"sm\">\n <div class=\"tw-text-center tw-py-4\">\n <cide-ele-icon name=\"cloud_upload\" class=\"tw-w-6 tw-h-6 tw-text-gray-400 tw-mx-auto tw-mb-2\"></cide-ele-icon>\n <p class=\"tw-text-xs tw-text-gray-600 tw-m-0\">Upload document files</p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-m-0\">PDF, Images, Word docs</p>\n </div>\n </cide-ele-file-input>\n\n <!-- Upload Status -->\n @if (getDocumentGroupId(i)) {\n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <h6 class=\"tw-text-xs tw-font-medium tw-text-gray-600 tw-m-0\">Upload Status:</h6>\n <span class=\"tw-text-xs tw-text-green-600 tw-font-medium\">\n \u2705 Files Uploaded\n </span>\n </div>\n <div class=\"tw-bg-green-50 tw-border tw-border-green-200 tw-rounded tw-p-2\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon name=\"cloud_done\" class=\"tw-w-4 tw-h-4 tw-text-green-500 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-flex tw-flex-col tw-flex-1 tw-min-w-0\">\n <span class=\"tw-text-xs tw-text-green-700 tw-font-medium\">Multiple files uploaded successfully</span>\n <span class=\"tw-text-xs tw-text-green-600 tw-font-mono tw-truncate\" [title]=\"'Group ID: ' + getDocumentGroupId(i)\">\n Group ID: {{ getDocumentGroupId(i).substring(0, 12) }}...\n </span>\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"tw-text-center tw-text-xs tw-text-gray-400 tw-py-2\">\n No files uploaded yet\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addFamilyDetail()\" leftIcon=\"add\">\n Add Family Member\n </button>\n </div>\n\n <div formArrayName=\"core_user_family_details\">\n @for (family of familyDetails(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Family Member {{ i + 1\n }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeFamilyDetail(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-3\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Family Member Name\" formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Family Member User\" [options]=\"userOptions(i)\"\n formControlName=\"syfdl_family_member_id_user\" placeholder=\"Select family member user\" size=\"md\"\n valueKey=\"_id\" labelKey=\"user_fullname\" [searchable]=\"true\"\n [loading]=\"userSearchLoading()[i] || false\" (searchChange)=\"onUserSearchChange($event, i)\"\n (change)=\"onUserSelectionChange($event, i)\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\" placeholder=\"Select relationship\" size=\"md\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\" placeholder=\"Select blood group\" size=\"md\" valueKey=\"_id\"\n labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Date of Birth\" formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"md\"\n [id]=\"'syfdl_family_member_dob['+i+']'\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Phone\" formControlName=\"syfdl_contact_phone\" type=\"tel\"\n placeholder=\"Enter contact phone\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\" type=\"email\"\n placeholder=\"Enter contact email\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Email ID\" formControlName=\"syfdl_contact_email_id\" type=\"email\"\n placeholder=\"Enter contact email ID\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\" type=\"tel\"\n placeholder=\"Enter contact number\" size=\"md\">\n </cide-ele-input>\n\n <div class=\"tw-flex tw-items-center tw-pt-6\">\n <cide-ele-input formControlName=\"syfdl_isactive\" type=\"checkbox\" label=\"Active\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Form Actions -->\n <div\n class=\"tw-flex tw-justify-end tw-gap-4 tw-py-2 tw-bg-white tw-border-t tw-border-gray-200 tw-sticky tw-bottom-0 tw-z-10\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || userMasterForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n Save User Master\n </button>\n </div>\n </form>\n</div>\n\n<!-- Template Renderers for Role Permissions Grid -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n @if (row.syme_type === 'module') {\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">folder</cide-ele-icon>\n } @else if (row.syme_type === 'section') {\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">folder_open</cide-ele-icon>\n } @else if (row.syme_type === 'menu') {\n <cide-ele-icon class=\"tw-text-purple-600 tw-w-4 tw-h-4\">menu</cide-ele-icon>\n } @else {\n <cide-ele-icon class=\"tw-text-gray-600 tw-w-4 tw-h-4\">description</cide-ele-icon>\n }\n </div>\n\n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"row.syme_title\">\n {{ row.syme_title || row.menu?.syme_title || row.menu?.syme_menu_name || 'Untitled' }}\n </div>\n <!-- Green pill indicator for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800 tw-whitespace-nowrap\">\n Assigned\n </span>\n }\n }\n </div>\n @if (row.permission?.sygms_name) {\n <div class=\"tw-text-xs tw-text-blue-500 tw-truncate\" [title]=\"row.permission?.sygms_name\">\n {{ row.permission?.sygms_name }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center\">\n @if (row.syme_type === 'module') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-blue-100 tw-text-blue-800\">\n Module\n </span>\n } @else if (row.syme_type === 'section') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Section\n </span>\n } @else if (row.syme_type === 'menu') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-purple-100 tw-text-purple-800\">\n Menu\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800\">\n {{ row.syme_type || 'Unknown' }}\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Checkbox Renderer Template -->\n<ng-template #permissionsCheckboxRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row.syme_type === 'menu' && row?.syme_permissions_id_sygms && row?.syme_permissions_id_sygms.length > 0) {\n @for (permissionId of row?.syme_permissions_id_sygms || []; track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input type=\"checkbox\" [checked]=\"isPermissionSelected(row._id, permissionId)\" [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">\n {{ getPermissionById(permissionId)?.sygms_name || 'Unknown' }}\n </label>\n </div>\n </div>\n }\n } @else {\n <!-- Show green checkmark for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section' || row.syme_type === 'title') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-green-100 tw-rounded-full\">\n <cide-ele-icon class=\"tw-text-green-600\" size=\"xs\">\n check\n </cide-ele-icon>\n </div>\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Menu Rights Permissions Renderer Template -->\n<ng-template #menuRightsPermissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n <!-- Role Rights Display -->\n @if (row.role_rights && row.role_rights.length > 0) {\n <div class=\"tw-mb-2\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Role Rights:</div>\n <div class=\"tw-flex tw-flex-wrap tw-gap-1\">\n @for (right of row.role_rights; track $index) {\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-blue-100 tw-text-blue-800 tw-rounded\">\n {{ right }}\n </span>\n }\n </div>\n </div>\n }\n\n\n <!-- Exception Indicator -->\n @if (row.hasException) {\n <div class=\"tw-mt-2\">\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-yellow-100 tw-text-yellow-800 tw-rounded\">\n Override\n </span>\n </div>\n } @else {\n <div class=\"tw-mt-2\">\n <span class=\"tw-text-xs tw-text-gray-400\">Default</span>\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Renderer Template -->\n<ng-template #permissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row._permissionValues && Object.keys(row._permissionValues).length > 0) {\n @for (permissionId of Object.keys(row._permissionValues); track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-input type=\"checkbox\" [ngModel]=\"row._permissionValues[permissionId].checked\"\n (ngModelChange)=\"onPermissionChangeSafe($event, row, permissionId)\"\n [id]=\"'permission-' + row._id + '-' + permissionId\" class=\"tw-h-4 tw-w-4\">\n </cide-ele-input>\n <label [for]=\"'permission-' + row._id + '-' + permissionId\" class=\"tw-text-xs tw-text-gray-700 tw-cursor-pointer\">\n {{ row._permissionValues[permissionId].permission?.sygms_title }}\n </label>\n </div>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">No permissions</span>\n }\n </div>\n</ng-template>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { kind: "component", type: CideEleFileInputComponent, selector: "cide-ele-file-input", inputs: ["label", "accept", "multiple", "disabled", "required", "helperText", "errorText", "showPreview", "previewWidth", "previewHeight", "previewBoxMode", "showFileName", "placeholderText", "placeholderIcon", "autoUpload", "uploadData"], outputs: ["fileChange", "uploadSuccess", "uploadError", "uploadProgressChange"] }, { kind: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "directive", type: CideLytFloatingUploadTriggerDirective, selector: "[cideFloatingUploadTrigger]", inputs: ["userId"] }] });
13347
14164
  }
13348
14165
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserCreateComponent, decorators: [{
13349
14166
  type: Component,
@@ -13359,8 +14176,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
13359
14176
  CideEleFileInputComponent,
13360
14177
  CideEleFileImageDirective,
13361
14178
  CideIconComponent,
13362
- CideEleDataGridComponent
13363
- ], template: "<!-- \n ENTERPRISE USER MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full tw-p-3\">\n <form class=\"tw-max-w-7xl tw-mx-auto tw-bg-transparent\" [formGroup]=\"userMasterForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- User Context Header -->\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-md tw-p-2 tw-mb-3 tw-shadow-sm\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-flex-wrap tw-gap-2\">\n <!-- User Basic Info Display -->\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-flex-wrap\">\n <!-- Profile Photo Preview -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div\n class=\"tw-w-8 tw-h-8 tw-rounded-full tw-bg-blue-100 tw-border tw-border-blue-200 tw-flex tw-items-center tw-justify-center tw-overflow-hidden\">\n @if (userMasterForm.get('user_photo_id_cyfm')?.value) {\n <img \n cideEleFileImage \n [fileId]=\"userMasterForm.get('user_photo_id_cyfm')?.value\" \n [altText]=\"'Profile Photo'\"\n class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <cide-ele-icon \n name=\"person\" \n class=\"tw-w-5 tw-h-5 tw-text-blue-600\">\n </cide-ele-icon>\n }\n </div>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-xs tw-font-medium tw-text-blue-900\">\n {{ getUserFullName() || 'New User' }}\n </span>\n <span class=\"tw-text-xs tw-text-blue-600\">\n {{ getUserUsername() || 'Username not set' }}\n </span>\n </div>\n </div>\n\n <!-- Contact Info -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">email</cide-ele-icon>\n <span>{{ getUserEmail() || 'Email not set' }}</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">phone</cide-ele-icon>\n <span>{{ getUserMobile() || 'Mobile not set' }}</span>\n </div>\n </div>\n\n <!-- Active Status -->\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (getUserActiveStatus()) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-700\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">check_circle</cide-ele-icon>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-700\">\n <cide-ele-icon variant=\"red\" size=\"xs\" class=\"tw-mr-1\">cancel</cide-ele-icon>\n Inactive\n </span>\n }\n </div>\n </div>\n\n <!-- Entity Info -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"blue\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-font-medium\">{{ getDefaultEntityName() }}</span>\n </div>\n } @else {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-500\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-italic\">No entity</span>\n </div>\n }\n\n <span class=\"tw-text-xs tw-text-gray-600 tw-px-2 tw-py-1 tw-bg-gray-100 tw-rounded\">\n {{ getEntityMappingCount() }} mapping(s)\n </span>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-p-0 tw-mb-2 tw-border-b tw-border-gray-200\">\n <cide-ele-tab [tabs]=\"userTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- User Basic Information Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n\n <!-- Top Section: Form Fields on Left, Profile Photo on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-6 tw-mb-6\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-6\">\n <!-- Name Fields - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-input id=\"user_firstname\" label=\"First Name *\" formControlName=\"user_firstname\"\n placeholder=\"Enter first name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_middlename\" label=\"Middle Name\" formControlName=\"user_middlename\"\n placeholder=\"Enter middle name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_lastname\" label=\"Last Name *\" formControlName=\"user_lastname\"\n placeholder=\"Enter last name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_fullname\" label=\"Full Name * (Auto-generated)\" formControlName=\"user_fullname\"\n placeholder=\"Auto-generated from name fields or enter manually\" [maxlength]=\"62\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Contact Information - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\n <cide-ele-input id=\"user_username\" label=\"Username *\" formControlName=\"user_username\"\n placeholder=\"Enter unique username\" [maxlength]=\"20\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_emailid\" label=\"Email ID *\" formControlName=\"user_emailid\" type=\"email\"\n placeholder=\"Enter valid email address\" [maxlength]=\"320\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_mobileno\" label=\"Mobile Number *\" formControlName=\"user_mobileno\" type=\"tel\"\n placeholder=\"Enter mobile number\" [maxlength]=\"15\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Profile Photo Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-p-0\">\n <cide-ele-file-input \n id=\"user_photo_id_cyfm\" \n formControlName=\"user_photo_id_cyfm\"\n accept=\"image/*\"\n [showPreview]=\"true\"\n [previewBoxMode]=\"true\"\n [showFileName]=\"false\"\n previewWidth=\"180px\"\n previewHeight=\"120px\"\n placeholderText=\"Upload Photo\"\n placeholderIcon=\"cloud_upload\"\n [autoUpload]=\"true\"\n [uploadData]=\"getProfilePhotoUploadData()\"\n (uploadSuccess)=\"onProfilePhotoUploadSuccess($event)\"\n (uploadError)=\"onProfilePhotoUploadError($event)\"\n (uploadProgressChange)=\"onProfilePhotoUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n\n\n\n <!-- Status Control -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-4\">\n <div class=\"tw-p-4 tw-bg-blue-50 tw-border tw-border-blue-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200 hover:tw-bg-blue-75\">\n <cide-ele-input type=\"checkbox\" label=\"Active User Status\" formControlName=\"user_isactive\"\n class=\"tw-h-5 tw-accent-blue-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-font-semibold tw-text-gray-700 tw-text-base\"></span>\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">Enable this user account for system\n access and operations</span>\n </label>\n </div>\n </div>\n </div>\n }\n\n @case ('auth') {\n <!-- Authentication Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <!-- Password Fields -->\n @if (shouldShowPasswordFields()) {\n <div class=\"tw-mb-6\">\n <!-- Password Fields Header for Edit Mode -->\n @if (isEditMode()) {\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Update Password</h6>\n <button type=\"button\"\n class=\"tw-px-3 tw-py-1 tw-bg-gray-100 tw-text-gray-600 tw-border tw-border-gray-300 tw-rounded-md tw-text-xs tw-font-medium hover:tw-bg-gray-200 tw-transition-colors\"\n (click)=\"cancelPasswordUpdate()\">\n Cancel Password Update\n </button>\n </div>\n }\n\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 md:tw-grid-cols-1 tw-gap-6\">\n <cide-ele-input id=\"user_password\" [label]=\"getPasswordFieldLabel()\" formControlName=\"user_password\"\n type=\"password\" placeholder=\"Enter secure password (min 8 characters)\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_confirm_password\" [label]=\"getPasswordConfirmLabel()\"\n formControlName=\"user_confirm_password\" type=\"password\" placeholder=\"Confirm your password\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n }\n\n <!-- Password Update Option for Edit Mode -->\n @if (isEditMode() && !shouldShowPasswordFields()) {\n <div class=\"tw-mb-6\">\n <div class=\"tw-p-4 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-blue-800 tw-mb-2\">Password Update</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-mb-3\">Current password will be kept. Click below to change\n password.</p>\n\n @if (hasPasswordInput()) {\n <div\n class=\"tw-mb-3 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded tw-text-sm tw-text-yellow-700\">\n <cide-ele-icon variant=\"yellow\" size=\"xs\" class=\"tw-mr-1\">warning</cide-ele-icon>\n Password fields contain text. Click \"Change Password\" to manage existing input.\n </div>\n }\n\n <button type=\"button\"\n class=\"tw-px-4 tw-py-2 tw-bg-blue-100 tw-text-blue-700 tw-border tw-border-blue-300 tw-rounded-md tw-text-sm tw-font-medium hover:tw-bg-blue-200 tw-transition-colors\"\n (click)=\"triggerPasswordUpdate()\">\n @if (hasPasswordInput()) {\n Manage Password Fields\n } @else {\n Change Password\n }\n </button>\n </div>\n </div>\n }\n\n <!-- Password Options -->\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-6 tw-mb-6\">\n <div class=\"tw-p-4 tw-bg-yellow-50 tw-border tw-border-yellow-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-gap-2 tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200\">\n <cide-ele-input type=\"checkbox\" label=\"Force Password Change on Login\"\n formControlName=\"user_passwordchangeonlogin\" class=\"tw-h-5 tw-accent-yellow-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">User will be required to change\n password on next login</span>\n </label>\n </div>\n </div>\n\n </div>\n }\n\n @case ('roles') {\n <!-- Entity, Roles & Permissions Mapping Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n\n\n\n <!-- Important Note -->\n <div class=\"tw-bg-amber-50 tw-border tw-border-amber-200 tw-rounded-lg tw-p-4 tw-mb-6\">\n <div class=\"tw-flex tw-items-start tw-gap-3\">\n <cide-ele-icon variant=\"amber\" size=\"lg\">info</cide-ele-icon>\n <div class=\"tw-flex-1\">\n <h4 class=\"tw-text-sm tw-font-semibold tw-text-amber-800 tw-mb-1\">Entity-Role Based Access</h4>\n <p class=\"tw-text-sm tw-text-amber-700 tw-mb-2\">User access is completely managed through entity-role\n mappings below. At least one entity mapping is required for user access.</p>\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mt-2 tw-p-2 tw-bg-amber-100 tw-rounded\">\n <cide-ele-icon variant=\"amber\" size=\"sm\">star</cide-ele-icon>\n <span class=\"tw-text-sm tw-text-amber-800\">\n <strong>Default Entity:</strong> {{ getDefaultEntityName() }}\n </span>\n </div>\n } @else {\n <div class=\"tw-text-sm tw-text-amber-600 tw-mt-2 tw-italic\">\n \u26A0\uFE0F No default entity selected. Please set one entity as default.\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Entity-Role Mapping Section -->\n <div class=\"tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg tw-p-6 tw-mb-6\">\n <div class=\"tw-flex tw-text-center tw-justify-between tw-items-center tw-mb-4\">\n <div>\n <h4 class=\"tw-text-sm tw-text-left tw-font-semibold tw-text-blue-900 tw-mb-1\">Entity-Role Mapping</h4>\n <p class=\"tw-text-sm tw-text-blue-700\">Map user to entities with specific roles and permissions</p>\n </div>\n <div class=\"tw-flex tw-flex-col tw-items-end\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addEntityMapping()\" leftIcon=\"add\"\n [disabled]=\"isAllEntitiesMapped()\">\n Add Entity Mapping\n </button>\n \n @if (isAllEntitiesMapped()) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-md tw-max-w-xs\">\n <p class=\"tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"info\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All available entities are already mapped.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div formArrayName=\"core_entity_mapping\">\n @for (mapping of entityMappings(); track $index; let i = $index) {\n <div class=\"tw-bg-white tw-border tw-border-blue-200 tw-rounded-xl tw-mb-6 tw-overflow-hidden tw-shadow-sm\"\n [formGroupName]=\"i\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-blue-100 tw-px-6 tw-py-3 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h5 class=\"tw-m-0 tw-text-blue-800 tw-text-sm tw-font-semibold\">Entity Mapping {{ i + 1 }}</h5>\n @if (mapping.syenm_isdefault) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">star</cide-ele-icon>\n Default\n </span>\n }\n </div>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n\n <div class=\"tw-p-6\">\n <!-- Entity and Role Selection -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <div>\n <cide-ele-select label=\"Entity *\" [options]=\"getFilteredEntityOptions(i)\" formControlName=\"syenm_entity_id_syen\"\n valueKey=\"_id\" labelKey=\"syen_name\" placeholder=\"Select entity\" size=\"md\"\n (change)=\"onEntityChange(i, $event)\">\n </cide-ele-select>\n \n @if (isAllEntitiesSelected(i)) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-md\">\n <p class=\"tw-text-xs tw-text-yellow-700\">\n <cide-ele-icon variant=\"warning\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All entities are already mapped. Remove another mapping to add this one.\n </p>\n </div>\n }\n </div>\n <cide-ele-select label=\"Role for this Entity\" [options]=\"getRoleOptionsForEntity(i)\"\n formControlName=\"syenm_role_id_syusrol\" valueKey=\"_id\" labelKey=\"syusrol_role_name\" placeholder=\"Select role for this entity\" size=\"md\"\n (change)=\"onRoleChange(i, $event)\">\n </cide-ele-select>\n </div>\n\n <!-- Role Permissions Grid -->\n @if (selectedEntityIndex() === i && selectedRoleId()) {\n <div class=\"tw-mb-6 tw-border tw-border-gray-200 tw-rounded-lg tw-bg-gray-50\">\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-white tw-rounded-t-lg\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">security</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800 tw-m-0\">Role Permissions Preview</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">(Read-only view of selected role permissions)</span>\n </div>\n </div>\n \n <div class=\"tw-p-4\">\n @if (loading()) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-py-8\">\n <div class=\"tw-animate-spin tw-rounded-full tw-h-8 tw-w-8 tw-border-b-2 tw-border-blue-600\"></div>\n <span class=\"tw-ml-2 tw-text-gray-600\">Loading role permissions...</span>\n </div>\n } @else if (error()) {\n <div class=\"tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n </div>\n </div>\n } @else {\n <cide-ele-data-grid \n [config]=\"rolePermissionsGridConfig()\" \n [templateRenderers]=\"templateRenderers\"\n (gridEvent)=\"onRolePermissionsGridEvent($event)\"\n class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n }\n </div>\n </div>\n }\n\n <!-- Entity-Specific Details -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Department for this Entity\" [options]=\"getDepartmentOptionsForEntity(i)\"\n formControlName=\"syenm_department_id_sydept\" (change)=\"onDepartmentChange($event)\" valueKey=\"_id\" labelKey=\"sydept_name\" placeholder=\"Select department\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Designation for this Entity\" [options]=\"getDesignationOptionsForEntity(i)\" valueKey=\"_id\" labelKey=\"sydsg_name\"\n formControlName=\"syenm_designation_id_sydsg\" placeholder=\"Select designation\" size=\"md\">\n </cide-ele-select>\n </div>\n\n <!-- Active Period for Entity Mapping -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Active From *\" [id]=\"'syenm_activefrom['+i+']'\"\n formControlName=\"syenm_activefrom\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Active Until\" [id]=\"'syenm_activeupto['+i+']'\"\n formControlName=\"syenm_activeupto\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Mapping Settings -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6 tw-mb-6\">\n <div class=\"tw-p-3 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Default Entity\" formControlName=\"syenm_isdefault\"\n (change)=\"onDefaultEntityChange(i, $event)\" class=\"tw-h-5 tw-accent-green-500\" />\n <span class=\"tw-text-xs tw-text-green-600 tw-block tw-mt-1\">Set as user's default entity (only one\n allowed)</span>\n </div>\n\n <div class=\"tw-p-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Active Mapping\" formControlName=\"syenm_isactive\"\n class=\"tw-h-5 tw-accent-blue-500\" />\n <span class=\"tw-text-xs tw-text-blue-600 tw-block tw-mt-1\">Enable this entity mapping</span>\n </div>\n </div>\n\n <!-- Menu Rights Grid for this Entity-Role -->\n <div class=\"tw-border-t tw-border-gray-200 tw-pt-4\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-mb-4\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Menu Rights & Permissions</h6>\n <div class=\"tw-flex tw-gap-2\">\n <button cideEleButton variant=\"secondary\" size=\"sm\" type=\"button\" (click)=\"refreshMenuRights(i)\"\n leftIcon=\"refresh\">\n Refresh Rights\n </button>\n </div>\n </div>\n\n @if (getMenuRightsForMapping(i).length > 0) {\n <!-- Menu Rights Tree Grid -->\n <div class=\"tw-border tw-border-gray-200 tw-rounded-lg tw-bg-white\">\n <div class=\"tw-px-4 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50 tw-rounded-t-lg\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">security</cide-ele-icon>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800 tw-m-0\">Menu Rights & Permissions</h6>\n <span class=\"tw-text-xs tw-text-gray-500\">(Editable permissions for this entity-role mapping)</span>\n </div>\n </div>\n \n <div class=\"tw-p-4\">\n <cide-ele-data-grid \n [config]=\"getMenuRightsGridConfig(i)\" \n [templateRenderers]=\"getMenuRightsTemplateRenderers(i)\"\n (gridEvent)=\"onMenuRightsGridEvent($event, i)\"\n class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n </div>\n </div>\n\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg\">\n <div class=\"tw-text-gray-400 tw-mb-3\">\n <cide-ele-icon variant=\"gray\" size=\"lg\">menu</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-2\">No Menu Rights Available</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-mb-3 tw-text-center\">Select both entity and role to load\n menu rights for this mapping.</p>\n @if (mapping.syenm_entity_id_syen?._id && mapping.syenm_role_id_syusrol) {\n <button cideEleButton variant=\"primary\" size=\"sm\" type=\"button\" (click)=\"loadMenuRights(i)\"\n leftIcon=\"refresh\">\n Load Menu Rights\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (entityMappings().length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-bg-white tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-text-blue-400 tw-mb-3\">\n <cide-ele-icon variant=\"blue\" size=\"lg\">business</cide-ele-icon>\n </div>\n <h4 class=\"tw-text-sm tw-font-medium tw-text-blue-800 tw-mb-2\">No Entity Mappings</h4>\n <p class=\"tw-text-blue-600 tw-mb-4 tw-text-center\">Add entity mappings to assign specific roles and\n permissions for different entities.</p>\n <button class=\"tw-mx-auto\" cideEleButton variant=\"primary\" size=\"md\" type=\"button\"\n (click)=\"addEntityMapping()\" leftIcon=\"add\">\n Add First Entity Mapping\n </button>\n </div>\n }\n </div>\n\n\n </div>\n }\n\n @case ('addresses') {\n <!-- Contact Addresses Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end\">\n <div class=\"tw-flex tw-justify-between tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addContactAddress()\"\n leftIcon=\"add\">\n Add New Address\n </button>\n </div>\n </div>\n\n <div formArrayName=\"core_user_contact_addresses\">\n @for (address of contactAddresses(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Address {{ i + 1 }}</h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Address Type\" [options]=\"addressTypeOptions()\" id=\"sycad_address_type_id_sygms\"\n formControlName=\"sycad_address_type_id_sygms\" placeholder=\"Select address type\" size=\"md\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Contact Person Name\" formControlName=\"sycad_contact_person_name\"\n placeholder=\"Enter contact person name\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-6\">\n <cide-ele-textarea label=\"Complete Address\" formControlName=\"sycad_contact_address\"\n placeholder=\"Enter complete address with area, city, and landmarks\" [rows]=\"3\" size=\"md\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code & City -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select \n label=\"Postal Code\"\n [options]=\"addressPostalCodes()[i] || []\" \n formControlName=\"sycad_contact_pin_sypin\"\n placeholder=\"Select postal code\"\n [searchable]=\"true\"\n [loading]=\"addressPostalCodesLoading()[i] || false\"\n (searchChange)=\"onPostalCodeSearch($event, i)\"\n (change)=\"onPostalCodeSelection($event, i)\"\n size=\"md\">\n </cide-ele-select>\n \n <cide-ele-input \n label=\"City\" \n formControlName=\"sycad_contact_city_sypin\"\n placeholder=\"Enter city\"\n size=\"md\">\n </cide-ele-input>\n </div>\n \n <!-- State & Country -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"State\" \n formControlName=\"sycad_contact_state_sypin\"\n placeholder=\"Enter state\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Country\" \n [options]=\"addressCountries()[i] || []\" \n formControlName=\"sycad_contact_country_syctr\"\n placeholder=\"Select country\"\n valueKey=\"_id\"\n labelKey=\"syctr_country_iso_name\"\n [searchable]=\"true\"\n (searchChange)=\"onCountrySearch($event, i)\"\n [loading]=\"addressCountriesLoading()[i] || false\"\n size=\"md\">\n </cide-ele-select>\n </div>\n\n <!-- Phone Numbers -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"Primary Phone\" \n formControlName=\"sycad_contact_phone\"\n type=\"tel\"\n placeholder=\"Enter primary phone number\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Alternate Phone\" \n formControlName=\"sycad_contact_phone_alt\"\n type=\"tel\"\n placeholder=\"Enter alternate phone number\"\n size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Fax & Email -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input \n label=\"Fax Number\" \n formControlName=\"sycad_contact_fax\"\n placeholder=\"Enter fax number\"\n size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input \n label=\"Primary Email\" \n formControlName=\"sycad_contact_email\"\n type=\"email\"\n placeholder=\"Enter primary email address\"\n size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Alternate Email -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-6\">\n <cide-ele-input \n label=\"Alternate Email\" \n formControlName=\"sycad_contact_email_alt\"\n type=\"email\"\n placeholder=\"Enter alternate email address\"\n size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('documents') {\n <!-- Documents Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addDocument()\" leftIcon=\"add\">\n Add Document\n </button>\n </div>\n\n <div formArrayName=\"core_user_documents\">\n @for (doc of documents(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Document {{ i + 1 }}</h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Document Type\" [options]=\"documentTypeOptions()\"\n formControlName=\"syusd_document_type_id_sygms\"\n placeholder=\"Select document type\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Document Number\" formControlName=\"syusd_doc_number\"\n placeholder=\"Enter document number\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Name as per Document\"\n formControlName=\"syusd_doc_name_as_per_doc\"\n placeholder=\"Enter name exactly as shown on document\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Photo Group\" [options]=\"photoGroupOptions()\"\n formControlName=\"syusd_photo_group_id_cyfm\"\n placeholder=\"Select photo group\" size=\"md\" valueKey=\"_id\" labelKey=\"cyfm_name\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Issue Date\" formControlName=\"syusd_doc_issue_date\"\n [id]=\"'syusd_doc_issue_date['+i+']'\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Expiry Date\" formControlName=\"syusd_doc_expiry_date\"\n [id]=\"'syusd_doc_expiry_date['+i+']'\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Document Verification Status\" [options]=\"documentVerificationStatusOptions()\"\n formControlName=\"syusd_doc_verification_status_id_sygms\"\n placeholder=\"Select verification status\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Document KYC Status\" [options]=\"documentKycStatusOptions()\"\n formControlName=\"syusd_doc_kyc_status_id_sygms\"\n placeholder=\"Select KYC status\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section -->\n <div class=\"tw-py-2 tw-border-b-0 tw-mb-2\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addFamilyDetail()\" leftIcon=\"add\">\n Add Family Member\n </button>\n </div>\n\n <div formArrayName=\"core_user_family_details\">\n @for (family of familyDetails(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Family Member {{ i + 1 }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeFamilyDetail(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Family Member Name\"\n formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select \n label=\"Family Member User\"\n [options]=\"userOptions(i)\"\n formControlName=\"syfdl_family_member_id_user\"\n placeholder=\"Select family member user\" \n size=\"md\" \n valueKey=\"_id\" \n labelKey=\"user_fullname\"\n [searchable]=\"true\"\n [loading]=\"userSearchLoading()[i] || false\"\n (searchChange)=\"onUserSearchChange($event, i)\"\n (change)=\"onUserSelectionChange($event, i)\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\"\n placeholder=\"Select relationship\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\"\n placeholder=\"Select blood group\" size=\"md\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Date of Birth\"\n formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"md\"\n [id]=\"'syfdl_family_member_dob['+i+']'\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Phone\"\n formControlName=\"syfdl_contact_phone\"\n type=\"tel\" placeholder=\"Enter contact phone\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\"\n type=\"email\" placeholder=\"Enter contact email\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Email ID\" formControlName=\"syfdl_contact_email_id\"\n type=\"email\" placeholder=\"Enter contact email ID\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\"\n type=\"tel\" placeholder=\"Enter contact number\" size=\"md\">\n </cide-ele-input>\n\n <div class=\"tw-flex tw-items-center tw-pt-6\">\n <cide-ele-input \n formControlName=\"syfdl_isactive\"\n type=\"checkbox\"\n label=\"Active\"\n size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Form Actions -->\n <div\n class=\"tw-flex tw-justify-end tw-gap-4 tw-py-2 tw-bg-white tw-border-t tw-border-gray-200 tw-sticky tw-bottom-0 tw-z-10\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || userMasterForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n Save User Master\n </button>\n </div>\n </form>\n</div>\n\n<!-- Template Renderers for Role Permissions Grid -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n @if (row.syme_type === 'module') {\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">folder</cide-ele-icon>\n } @else if (row.syme_type === 'section') {\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">folder_open</cide-ele-icon>\n } @else if (row.syme_type === 'menu') {\n <cide-ele-icon class=\"tw-text-purple-600 tw-w-4 tw-h-4\">menu</cide-ele-icon>\n } @else {\n <cide-ele-icon class=\"tw-text-gray-600 tw-w-4 tw-h-4\">description</cide-ele-icon>\n }\n </div>\n \n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" \n [title]=\"row.syme_title\">\n {{ row.syme_title || row.menu?.syme_title || row.menu?.syme_menu_name || 'Untitled' }}\n </div>\n <!-- Green pill indicator for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800 tw-whitespace-nowrap\">\n Assigned\n </span>\n }\n }\n </div>\n @if (row.permission?.sygms_name) {\n <div class=\"tw-text-xs tw-text-blue-500 tw-truncate\" \n [title]=\"row.permission?.sygms_name\">\n {{ row.permission?.sygms_name }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center\">\n @if (row.syme_type === 'module') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-blue-100 tw-text-blue-800\">\n Module\n </span>\n } @else if (row.syme_type === 'section') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Section\n </span>\n } @else if (row.syme_type === 'menu') {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-purple-100 tw-text-purple-800\">\n Menu\n </span>\n } @else {\n <span class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800\">\n {{ row.syme_type || 'Unknown' }}\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Checkbox Renderer Template -->\n<ng-template #permissionsCheckboxRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row.syme_type === 'menu' && row?.syme_permissions_id_sygms && row?.syme_permissions_id_sygms.length > 0) {\n @for (permissionId of row?.syme_permissions_id_sygms || []; track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"isPermissionSelected(row._id, permissionId)\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">\n {{ getPermissionById(permissionId)?.sygms_name || 'Unknown' }}\n </label>\n </div>\n </div>\n }\n } @else {\n <!-- Show green checkmark for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section' || row.syme_type === 'title') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-green-100 tw-rounded-full\">\n <cide-ele-icon \n class=\"tw-text-green-600\" \n size=\"xs\">\n check\n </cide-ele-icon>\n </div>\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Menu Rights Permissions Renderer Template -->\n<ng-template #menuRightsPermissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n <!-- Role Rights Display -->\n @if (row.role_rights && row.role_rights.length > 0) {\n <div class=\"tw-mb-2\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Role Rights:</div>\n <div class=\"tw-flex tw-flex-wrap tw-gap-1\">\n @for (right of row.role_rights; track $index) {\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-blue-100 tw-text-blue-800 tw-rounded\">\n {{ right }}\n </span>\n }\n </div>\n </div>\n }\n \n <!-- Individual Permission Controls -->\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-2 tw-w-full\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.create\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-green-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-green-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Create</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.read\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Read</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.update\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-yellow-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-yellow-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Update</label>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input \n type=\"checkbox\"\n [checked]=\"row.delete\"\n [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-red-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-red-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">Delete</label>\n </div>\n </div>\n \n <!-- Exception Indicator -->\n @if (row.hasException) {\n <div class=\"tw-mt-2\">\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-yellow-100 tw-text-yellow-800 tw-rounded\">\n Override\n </span>\n </div>\n } @else {\n <div class=\"tw-mt-2\">\n <span class=\"tw-text-xs tw-text-gray-400\">Default</span>\n </div>\n }\n </div>\n</ng-template>" }]
14179
+ CideEleDataGridComponent,
14180
+ CideLytFloatingUploadTriggerDirective
14181
+ ], template: "<!-- \n ENTERPRISE USER MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full tw-p-1 tw-pt-2\">\n <form class=\"tw-max-w-7xl tw-mx-auto tw-bg-transparent\" [formGroup]=\"userMasterForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- Success/Error Messages -->\n @if (success()) {\n <div class=\"tw-mb-4 tw-p-4 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-md tw-shadow-sm\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"check_circle\" class=\"tw-text-green-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-green-800 tw-m-0\">Success</h3>\n <p class=\"tw-text-sm tw-text-green-700 tw-mt-1 tw-m-0\">{{ success() }}</p>\n </div>\n <button type=\"button\" (click)=\"success.set(null)\" class=\"tw-ml-auto tw-text-green-400 hover:tw-text-green-600\">\n <cide-ele-icon name=\"close\" class=\"tw-w-4 tw-h-4\"></cide-ele-icon>\n </button>\n </div>\n </div>\n }\n @if (error()) {\n <div class=\"tw-mb-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md tw-shadow-sm\">\n <div class=\"tw-flex tw-items-start\">\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\n </div>\n <button type=\"button\" (click)=\"error.set(null)\" class=\"tw-ml-auto tw-text-red-400 hover:tw-text-red-600\">\n <cide-ele-icon name=\"close\" class=\"tw-w-4 tw-h-4\"></cide-ele-icon>\n </button>\n </div>\n </div>\n }\n\n <!-- User Context Header -->\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-md tw-p-1 tw-mb-2 tw-shadow-sm\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-flex-wrap tw-gap-2\">\n <!-- User Basic Info Display -->\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-flex-wrap\">\n <!-- Profile Photo Preview -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div\n class=\"tw-w-8 tw-h-8 tw-rounded-full tw-bg-blue-100 tw-border tw-border-blue-200 tw-flex tw-items-center tw-justify-center tw-overflow-hidden\">\n @if (userMasterForm.get('user_photo_id_cyfm')?.value) {\n <img cideEleFileImage [fileId]=\"userMasterForm.get('user_photo_id_cyfm')?.value\"\n [altText]=\"'Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <cide-ele-icon name=\"person\" class=\"tw-w-5 tw-h-5 tw-text-blue-600\">\n </cide-ele-icon>\n }\n </div>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-xs tw-font-medium tw-text-blue-900\">\n {{ getUserFullName() || 'New User' }}\n </span>\n <span class=\"tw-text-xs tw-text-blue-600\">\n {{ getUserUsername() || 'Username not set' }}\n </span>\n </div>\n </div>\n\n <!-- Contact Info -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">email</cide-ele-icon>\n <span>{{ getUserEmail() || 'Email not set' }}</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-700\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">phone</cide-ele-icon>\n <span>{{ getUserMobile() || 'Mobile not set' }}</span>\n </div>\n </div>\n\n <!-- Active Status -->\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n @if (getUserActiveStatus()) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-700\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">check_circle</cide-ele-icon>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-700\">\n <cide-ele-icon variant=\"red\" size=\"xs\" class=\"tw-mr-1\">cancel</cide-ele-icon>\n Inactive\n </span>\n }\n </div>\n </div>\n\n <!-- Entity Info -->\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"blue\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-font-medium\">{{ getDefaultEntityName() }}</span>\n </div>\n } @else {\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-xs tw-text-gray-500\">\n <cide-ele-icon variant=\"gray\" size=\"xs\">business</cide-ele-icon>\n <span class=\"tw-italic\">No entity</span>\n </div>\n }\n\n <span class=\"tw-text-xs tw-text-gray-600 tw-px-2 tw-py-1 tw-bg-gray-100 tw-rounded\">\n {{ getEntityMappingCount() }} mapping(s)\n </span>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-p-0 tw-mb-2 tw-border-b tw-border-gray-200\">\n <cide-ele-tab [tabs]=\"userTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- User Basic Information Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n\n <!-- Top Section: Form Fields on Left, Profile Photo on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4 tw-mb-4\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-4\">\n <!-- Name Fields - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4\">\n <cide-ele-input id=\"user_firstname\" label=\"First Name *\" formControlName=\"user_firstname\"\n placeholder=\"Enter first name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_middlename\" label=\"Middle Name\" formControlName=\"user_middlename\"\n placeholder=\"Enter middle name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_lastname\" label=\"Last Name *\" formControlName=\"user_lastname\"\n placeholder=\"Enter last name\" [maxlength]=\"20\" size=\"md\" (ngModelChange)=\"onNameFieldChange()\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_fullname\" label=\"Full Name * (Auto-generated)\" formControlName=\"user_fullname\"\n placeholder=\"Auto-generated from name fields or enter manually\" [maxlength]=\"62\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Contact Information - All in One Row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-3 tw-gap-4\">\n <cide-ele-input id=\"user_username\" label=\"Username *\" formControlName=\"user_username\"\n placeholder=\"Enter unique username\" [maxlength]=\"20\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_emailid\" label=\"Email ID *\" formControlName=\"user_emailid\" type=\"email\"\n placeholder=\"Enter valid email address\" [maxlength]=\"320\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_mobileno\" label=\"Mobile Number *\" formControlName=\"user_mobileno\" type=\"tel\"\n placeholder=\"Enter mobile number\" [maxlength]=\"15\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Profile Photo Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-p-0\">\n <cide-ele-file-input id=\"user_photo_id_cyfm\" formControlName=\"user_photo_id_cyfm\" accept=\"image/*\"\n [showPreview]=\"true\" [previewBoxMode]=\"true\" [showFileName]=\"false\" previewWidth=\"180px\"\n previewHeight=\"120px\" placeholderText=\"Upload Photo\" placeholderIcon=\"cloud_upload\" [autoUpload]=\"true\"\n [uploadData]=\"getProfilePhotoUploadData()\" (uploadSuccess)=\"onProfilePhotoUploadSuccess($event)\"\n (uploadError)=\"onProfilePhotoUploadError($event)\"\n (uploadProgressChange)=\"onProfilePhotoUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n\n\n\n <!-- Status Control -->\n <div class=\"tw-grid tw-grid-cols-1 tw-mb-2\">\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200 hover:tw-bg-blue-75\">\n <cide-ele-input type=\"checkbox\" label=\"Active User Status\" formControlName=\"user_isactive\"\n class=\"tw-h-5 tw-accent-blue-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-font-semibold tw-text-gray-700 tw-text-base\"></span>\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">Enable this user account for system\n access and operations</span>\n </label>\n </div>\n </div>\n </div>\n }\n\n @case ('auth') {\n <!-- Authentication Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <!-- Password Fields -->\n @if (shouldShowPasswordFields()) {\n <div class=\"tw-mb-4\">\n <!-- Password Fields Header for Edit Mode -->\n @if (isEditMode()) {\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-3\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-800\">Update Password</h6>\n <button type=\"button\"\n class=\"tw-px-3 tw-py-1 tw-bg-gray-100 tw-text-gray-600 tw-border tw-border-gray-300 tw-rounded-md tw-text-xs tw-font-medium hover:tw-bg-gray-200 tw-transition-colors\"\n (click)=\"cancelPasswordUpdate()\">\n Cancel Password Update\n </button>\n </div>\n }\n\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 md:tw-grid-cols-1 tw-gap-6\">\n <cide-ele-input id=\"user_password\" [label]=\"getPasswordFieldLabel()\" formControlName=\"user_password\"\n type=\"password\" placeholder=\"Enter secure password (min 8 characters)\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input id=\"user_confirm_password\" [label]=\"getPasswordConfirmLabel()\"\n formControlName=\"user_confirm_password\" type=\"password\" placeholder=\"Confirm your password\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n }\n\n <!-- Password Update Option for Edit Mode -->\n @if (isEditMode() && !shouldShowPasswordFields()) {\n <div class=\"tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-blue-800 tw-mb-2\">Password Update</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-mb-3\">Current password will be kept. Click below to change\n password.</p>\n\n @if (hasPasswordInput()) {\n <div\n class=\"tw-mb-3 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded tw-text-sm tw-text-yellow-700\">\n <cide-ele-icon variant=\"yellow\" size=\"xs\" class=\"tw-mr-1\">warning</cide-ele-icon>\n Password fields contain text. Click \"Change Password\" to manage existing input.\n </div>\n }\n\n <button type=\"button\"\n class=\"tw-px-4 tw-py-2 tw-bg-blue-100 tw-text-blue-700 tw-border tw-border-blue-300 tw-rounded-md tw-text-sm tw-font-medium hover:tw-bg-blue-200 tw-transition-colors\"\n (click)=\"triggerPasswordUpdate()\">\n @if (hasPasswordInput()) {\n Manage Password Fields\n } @else {\n Change Password\n }\n </button>\n </div>\n </div>\n }\n\n <!-- Password Options -->\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-4 tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-100 tw-rounded-lg\">\n <label\n class=\"tw-flex tw-flex-col tw-gap-2 tw-cursor-pointer tw-py-2 tw-bg-transparent tw-border-none tw-rounded-none tw-transition-all tw-duration-200\">\n <cide-ele-input type=\"checkbox\" label=\"Force Password Change on Login\"\n formControlName=\"user_passwordchangeonlogin\" class=\"tw-h-5 tw-accent-yellow-500 tw-rounded tw-mb-1\" />\n <span class=\"tw-text-sm tw-text-gray-600 tw-mt-1 tw-leading-relaxed\">User will be required to change\n password on next login</span>\n </label>\n </div>\n </div>\n\n </div>\n }\n\n @case ('roles') {\n <!-- Entity, Roles & Permissions Mapping Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n\n\n\n <!-- Important Note -->\n <div class=\"tw-bg-amber-50 tw-border tw-border-amber-200 tw-rounded-lg tw-p-2 tw-mb-4\">\n <div class=\"tw-flex tw-items-start tw-gap-3\">\n <cide-ele-icon variant=\"amber\" size=\"lg\">info</cide-ele-icon>\n <div class=\"tw-flex-1\">\n <h4 class=\"tw-text-sm tw-font-semibold tw-text-amber-800 tw-mb-1\">Entity-Role Based Access</h4>\n <p class=\"tw-text-sm tw-text-amber-700 tw-mb-2\">User access is completely managed through entity-role\n mappings below. At least one entity mapping is required for user access.</p>\n @if (hasDefaultEntity()) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-mt-2 tw-p-2 tw-bg-amber-100 tw-rounded\">\n <cide-ele-icon variant=\"amber\" size=\"sm\">star</cide-ele-icon>\n <span class=\"tw-text-sm tw-text-amber-800\">\n <strong>Default Entity:</strong> {{ getDefaultEntityName() }}\n </span>\n </div>\n } @else {\n <div class=\"tw-text-sm tw-text-amber-600 tw-mt-2 tw-italic\">\n \u26A0\uFE0F No default entity selected. Please set one entity as default.\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Entity-Role Mapping Section -->\n <div class=\"tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg tw-p-3 tw-mb-4\">\n <div class=\"tw-flex tw-text-center tw-justify-between tw-items-center tw-mb-4\">\n <div>\n <h4 class=\"tw-text-sm tw-text-left tw-font-semibold tw-text-blue-900 tw-mb-1\">Entity-Role Mapping</h4>\n <p class=\"tw-text-sm tw-text-blue-700\">Map user to entities with specific roles and permissions</p>\n </div>\n <div class=\"tw-flex tw-flex-col tw-items-end\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addEntityMapping()\"\n leftIcon=\"add\" [disabled]=\"isAllEntitiesMapped()\">\n Add Entity Mapping\n </button>\n\n @if (isAllEntitiesMapped()) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-md tw-max-w-xs\">\n <p class=\"tw-text-xs tw-text-blue-700\">\n <cide-ele-icon variant=\"info\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All available entities are already mapped.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div formArrayName=\"core_entity_mapping\">\n @for (mapping of entityMappings(); track $index; let i = $index) {\n <div class=\"tw-bg-white tw-border tw-border-blue-200 tw-rounded-xl tw-mb-6 tw-overflow-hidden tw-shadow-sm\"\n [formGroupName]=\"i\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-blue-100 tw-px-6 tw-py-3 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-blue-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h5 class=\"tw-m-0 tw-text-blue-800 tw-text-sm tw-font-semibold\">Entity Mapping {{ i + 1 }}</h5>\n @if (mapping.syenm_isdefault) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <cide-ele-icon variant=\"green\" size=\"xs\" class=\"tw-mr-1\">star</cide-ele-icon>\n Default\n </span>\n }\n </div>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n\n <div>\n <!-- Entity and Role Selection -->\n <div class=\"tw-grid tw-px-3 tw-py-1 tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-4 tw-mb-4\">\n <div>\n <cide-ele-select label=\"Entity *\" [options]=\"getFilteredEntityOptions(i)\"\n formControlName=\"syenm_entity_id_syen\" valueKey=\"_id\" labelKey=\"syen_name\"\n placeholder=\"Select entity\" size=\"md\" (change)=\"onEntityChange(i, $event)\">\n </cide-ele-select>\n\n @if (isAllEntitiesSelected(i)) {\n <div class=\"tw-mt-2 tw-p-2 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-md\">\n <p class=\"tw-text-xs tw-text-yellow-700\">\n <cide-ele-icon variant=\"warning\" size=\"xs\" class=\"tw-mr-1\">info</cide-ele-icon>\n All entities are already mapped. Remove another mapping to add this one.\n </p>\n </div>\n }\n </div>\n <cide-ele-select label=\"Role for this Entity\" [options]=\"getRoleOptionsForEntity(i)\"\n formControlName=\"syenm_role_id_syusrol\" valueKey=\"_id\" labelKey=\"syusrol_role_name\"\n placeholder=\"Select role for this entity\" size=\"md\" (change)=\"onRoleChange(i, $event)\">\n </cide-ele-select>\n </div>\n\n\n <!-- Entity-Specific Details and Active Period - All in One Row -->\n <div class=\"tw-grid tw-px-3 tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4 tw-mb-4\">\n <cide-ele-select label=\"Department for this Entity\" [options]=\"getDepartmentOptionsForEntity(i)\"\n formControlName=\"syenm_department_id_sydept\" (change)=\"onDepartmentChange($event)\" valueKey=\"_id\"\n labelKey=\"sydept_name\" placeholder=\"Select department\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Designation for this Entity\" [options]=\"getDesignationOptionsForEntity(i)\"\n valueKey=\"_id\" labelKey=\"sydsg_name\" formControlName=\"syenm_designation_id_sydsg\"\n placeholder=\"Select designation\" size=\"md\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Active From *\" [id]=\"'syenm_activefrom['+i+']'\"\n formControlName=\"syenm_activefrom\" type=\"date\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Active Until\" [id]=\"'syenm_activeupto['+i+']'\"\n formControlName=\"syenm_activeupto\" type=\"date\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <!-- Mapping Settings -->\n <div class=\"tw-grid tw-px-3 tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-4 tw-mb-4\">\n <div class=\"tw-p-2 tw-bg-green-50 tw-border tw-border-green-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Default Entity\" formControlName=\"syenm_isdefault\"\n (change)=\"onDefaultEntityChange(i, $event)\" class=\"tw-h-5 tw-accent-green-500\" />\n <span class=\"tw-text-xs tw-text-green-600 tw-block tw-mt-1\">Set as user's default entity (only one\n allowed)</span>\n </div>\n\n <div class=\"tw-p-2 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <cide-ele-input type=\"checkbox\" label=\"Active Mapping\" formControlName=\"syenm_isactive\"\n class=\"tw-h-5 tw-accent-blue-500\" />\n <span class=\"tw-text-xs tw-text-blue-600 tw-block tw-mt-1\">Enable this entity mapping</span>\n </div>\n </div>\n\n <!-- Menu Rights Grid for this Entity-Role -->\n <div class=\"tw-border-t tw-border-gray-200\">\n\n @if (getMenuRightsForMapping(i).length > 0) {\n <!-- Menu Rights Tree Grid -->\n\n <cide-ele-data-grid [config]=\"getMenuRightsGridConfig(i)\"\n [templateRenderers]=\"getMenuRightsTemplateRenderers(i)\"\n (gridEvent)=\"onMenuRightsGridEvent($event, i)\" class=\"tw-h-96 tw-w-full\">\n </cide-ele-data-grid>\n\n } @else {\n <div class=\"tw-text-center tw-py-8 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg\">\n <div class=\"tw-text-gray-400 tw-mb-3\">\n <cide-ele-icon variant=\"gray\" size=\"lg\">menu</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-medium tw-text-gray-600 tw-mb-2\">No Menu Rights Available</h6>\n <p class=\"tw-text-xs tw-text-gray-500 tw-mb-3 tw-text-center\">Select both entity and role to\n automatically load\n menu rights for this mapping.</p>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n @if (entityMappings().length === 0) {\n <div class=\"tw-text-center tw-py-8 tw-bg-white tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-text-blue-400 tw-mb-3\">\n <cide-ele-icon variant=\"blue\" size=\"lg\">business</cide-ele-icon>\n </div>\n <h4 class=\"tw-text-sm tw-font-medium tw-text-blue-800 tw-mb-2\">No Entity Mappings</h4>\n <p class=\"tw-text-blue-600 tw-mb-4 tw-text-center\">Add entity mappings to assign specific roles and\n permissions for different entities.</p>\n <button class=\"tw-mx-auto\" cideEleButton variant=\"primary\" size=\"md\" type=\"button\"\n (click)=\"addEntityMapping()\" leftIcon=\"add\">\n Add First Entity Mapping\n </button>\n </div>\n }\n </div>\n\n\n </div>\n }\n\n @case ('addresses') {\n <!-- Contact Addresses Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end\">\n <div class=\"tw-flex tw-justify-between tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addContactAddress()\"\n leftIcon=\"add\">\n Add New Address\n </button>\n </div>\n </div>\n\n <div formArrayName=\"core_user_contact_addresses\">\n @for (address of contactAddresses(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-4 tw-py-2 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <!-- Use address type as header instead of generic \"Address X\" -->\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">\n {{ getAddressTypeLabel(i) || ('Address ' + (i + 1)) }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-4\">\n <!-- Main Layout: Inputs on Left, Address Textarea on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n \n <!-- Left Side: Input Fields (3/4 width) -->\n <div class=\"lg:tw-col-span-3\">\n <!-- Row 1: Address Type, Contact Person -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Address Type\" [options]=\"addressTypeOptions()\" id=\"sycad_address_type_id_sygms\"\n formControlName=\"sycad_address_type_id_sygms\" placeholder=\"Select type\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\" (change)=\"onAddressTypeChange(i)\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Contact Person\" formControlName=\"sycad_contact_person_name\"\n placeholder=\"Enter contact person\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 2: Postal Code, City, State, Country -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-3\">\n <cide-ele-select label=\"Postal Code\" [options]=\"addressPostalCodes()[i] || []\"\n formControlName=\"sycad_contact_pin_sypin\" placeholder=\"Select postal code\" [searchable]=\"true\"\n [loading]=\"addressPostalCodesLoading()[i] || false\" (searchChange)=\"onPostalCodeSearch($event, i)\"\n (change)=\"onPostalCodeSelection($event, i)\" size=\"sm\">\n </cide-ele-select>\n\n <cide-ele-input label=\"City\" formControlName=\"sycad_contact_city_sypin\" placeholder=\"Enter city\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"State\" formControlName=\"sycad_contact_state_sypin\" placeholder=\"Enter state\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Country\" [options]=\"addressCountries()[i] || []\"\n formControlName=\"sycad_contact_country_syctr\" placeholder=\"Select country\" valueKey=\"_id\"\n labelKey=\"syctr_country_iso_name\" [searchable]=\"true\" (searchChange)=\"onCountrySearch($event, i)\"\n [loading]=\"addressCountriesLoading()[i] || false\" size=\"sm\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Right Side: Address Textarea (1/4 width, spans 2 rows) -->\n <div class=\"lg:tw-col-span-1 lg:tw-row-span-2 tw-flex tw-flex-col\">\n <cide-ele-textarea label=\"Complete Address\" formControlName=\"sycad_contact_address\"\n placeholder=\"Enter complete address with area, city, and landmarks\" [rows]=\"4\" size=\"sm\"\n class=\"tw-h-full\">\n </cide-ele-textarea>\n </div>\n </div>\n\n <!-- Contact Details: Primary Phone, Alt Phone, Fax, Primary Email in 4 columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-4 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Primary Phone\" formControlName=\"sycad_contact_phone\" type=\"tel\"\n placeholder=\"Primary phone\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Alternate Phone\" formControlName=\"sycad_contact_phone_alt\" type=\"tel\"\n placeholder=\"Alternate phone\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Fax Number\" formControlName=\"sycad_contact_fax\" placeholder=\"Fax number\"\n size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Primary Email\" formControlName=\"sycad_contact_email\" type=\"email\"\n placeholder=\"Primary email\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Alternate Email in single row -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-input label=\"Alternate Email\" formControlName=\"sycad_contact_email_alt\" type=\"email\"\n placeholder=\"Alternate email address\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('documents') {\n <!-- Documents Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addDocument()\" leftIcon=\"add\">\n Add Document\n </button>\n </div>\n\n <div formArrayName=\"core_user_documents\">\n @for (doc of documents(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-4 tw-py-2 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">\n {{ getDocumentTypeLabel(i) || ('Document ' + (i + 1)) }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-4\">\n <!-- Main Layout: Inputs on Left, File Upload on Right -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-3 tw-gap-4\">\n \n <!-- Left Side: Document Information (2/3 width) -->\n <div class=\"lg:tw-col-span-2\">\n <!-- Row 1: Document Type, Document Number, Name as per Document -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Document Type\" [options]=\"documentTypeOptions()\"\n formControlName=\"syusd_document_type_id_sygms\" placeholder=\"Select type\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\" (change)=\"onDocumentTypeChange(i)\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Document Number\" formControlName=\"syusd_doc_number\"\n placeholder=\"Document number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Name as per Document\" formControlName=\"syusd_doc_name_as_per_doc\"\n placeholder=\"Name on document\" size=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 2: Issue Date, Expiry Date, Photo Group -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Issue Date\" formControlName=\"syusd_doc_issue_date\"\n [id]=\"'syusd_doc_issue_date['+i+']'\" type=\"date\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Expiry Date\" formControlName=\"syusd_doc_expiry_date\"\n [id]=\"'syusd_doc_expiry_date['+i+']'\" type=\"date\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Photo Group\" [options]=\"photoGroupOptions()\"\n formControlName=\"syusd_photo_group_id_cyfm\" placeholder=\"Select group\" size=\"sm\" valueKey=\"_id\"\n labelKey=\"cyfm_name\">\n </cide-ele-select>\n </div>\n\n <!-- Row 3: Verification Status, KYC Status -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-3\">\n <cide-ele-select label=\"Verification Status\" [options]=\"documentVerificationStatusOptions()\"\n formControlName=\"syusd_doc_verification_status_id_sygms\" placeholder=\"Select status\"\n size=\"sm\" valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"KYC Status\" [options]=\"documentKycStatusOptions()\"\n formControlName=\"syusd_doc_kyc_status_id_sygms\" placeholder=\"Select KYC status\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n </div>\n\n <!-- Right Side: File Upload (1/3 width) -->\n <div class=\"lg:tw-col-span-1\">\n <div class=\"tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-lg tw-p-3 tw-h-full\">\n <h5 class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-mb-3 tw-m-0\">Document Files</h5>\n \n <!-- File Upload Input -->\n {{documentsFormArray.at(i).get('syusd_photo_group_id_cyfm')?.value}}\n <cide-ele-file-input\n [id]=\"'document-files-' + i\"\n [multiple]=\"true\"\n formControlName=\"syusd_photo_group_id_cyfm\"\n [accept]=\"'.pdf,.jpg,.jpeg,.png,.doc,.docx'\"\n [autoUpload]=\"true\"\n [uploadData]=\"getDocumentUploadData(i)\"\n (change)=\"onDocumentFilesSelected($event, i)\"\n (uploadSuccess)=\"onDocumentUploadSuccess($event, i)\"\n (uploadError)=\"onDocumentUploadError($event, i)\"\n (uploadProgressChange)=\"onDocumentUploadProgress($event, i)\"\n cideFloatingUploadTrigger\n class=\"tw-mb-3\"\n size=\"sm\">\n <div class=\"tw-text-center tw-py-4\">\n <cide-ele-icon name=\"cloud_upload\" class=\"tw-w-6 tw-h-6 tw-text-gray-400 tw-mx-auto tw-mb-2\"></cide-ele-icon>\n <p class=\"tw-text-xs tw-text-gray-600 tw-m-0\">Upload document files</p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-m-0\">PDF, Images, Word docs</p>\n </div>\n </cide-ele-file-input>\n\n <!-- Upload Status -->\n @if (getDocumentGroupId(i)) {\n <div class=\"tw-space-y-2\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-2\">\n <h6 class=\"tw-text-xs tw-font-medium tw-text-gray-600 tw-m-0\">Upload Status:</h6>\n <span class=\"tw-text-xs tw-text-green-600 tw-font-medium\">\n \u2705 Files Uploaded\n </span>\n </div>\n <div class=\"tw-bg-green-50 tw-border tw-border-green-200 tw-rounded tw-p-2\">\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon name=\"cloud_done\" class=\"tw-w-4 tw-h-4 tw-text-green-500 tw-flex-shrink-0\"></cide-ele-icon>\n <div class=\"tw-flex tw-flex-col tw-flex-1 tw-min-w-0\">\n <span class=\"tw-text-xs tw-text-green-700 tw-font-medium\">Multiple files uploaded successfully</span>\n <span class=\"tw-text-xs tw-text-green-600 tw-font-mono tw-truncate\" [title]=\"'Group ID: ' + getDocumentGroupId(i)\">\n Group ID: {{ getDocumentGroupId(i).substring(0, 12) }}...\n </span>\n </div>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"tw-text-center tw-text-xs tw-text-gray-400 tw-py-2\">\n No files uploaded yet\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section -->\n <div class=\"tw-py-1 tw-border-b-0 tw-mb-1\">\n <div class=\"tw-flex tw-justify-end tw-items-end tw-mb-2 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"md\" type=\"button\" (click)=\"addFamilyDetail()\" leftIcon=\"add\">\n Add Family Member\n </button>\n </div>\n\n <div formArrayName=\"core_user_family_details\">\n @for (family of familyDetails(); track $index; let i = $index) {\n <div [formGroupName]=\"i\"\n class=\"tw-bg-white tw-border tw-border-gray-200 tw-rounded-xl tw-mb-8 tw-overflow-hidden tw-transition-all tw-duration-300 hover:tw-shadow-lg tw-shadow-sm\">\n <div\n class=\"tw-bg-gradient-to-r tw-from-gray-50 tw-to-gray-100 tw-px-6 tw-py-1 tw-flex tw-justify-between tw-items-center tw-border-b tw-border-gray-200\">\n <h4 class=\"tw-m-0 tw-text-gray-700 tw-text-sm tw-font-semibold tw-tracking-tight\">Family Member {{ i + 1\n }}\n </h4>\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeFamilyDetail(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n </div>\n <div class=\"tw-p-3\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Family Member Name\" formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Family Member User\" [options]=\"userOptions(i)\"\n formControlName=\"syfdl_family_member_id_user\" placeholder=\"Select family member user\" size=\"md\"\n valueKey=\"_id\" labelKey=\"user_fullname\" [searchable]=\"true\"\n [loading]=\"userSearchLoading()[i] || false\" (searchChange)=\"onUserSearchChange($event, i)\"\n (change)=\"onUserSelectionChange($event, i)\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\" placeholder=\"Select relationship\" size=\"md\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\" placeholder=\"Select blood group\" size=\"md\" valueKey=\"_id\"\n labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Date of Birth\" formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"md\"\n [id]=\"'syfdl_family_member_dob['+i+']'\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Phone\" formControlName=\"syfdl_contact_phone\" type=\"tel\"\n placeholder=\"Enter contact phone\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6 tw-mb-6\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\" type=\"email\"\n placeholder=\"Enter contact email\" size=\"md\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Email ID\" formControlName=\"syfdl_contact_email_id\" type=\"email\"\n placeholder=\"Enter contact email ID\" size=\"md\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\" type=\"tel\"\n placeholder=\"Enter contact number\" size=\"md\">\n </cide-ele-input>\n\n <div class=\"tw-flex tw-items-center tw-pt-6\">\n <cide-ele-input formControlName=\"syfdl_isactive\" type=\"checkbox\" label=\"Active\" size=\"md\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Form Actions -->\n <div\n class=\"tw-flex tw-justify-end tw-gap-4 tw-py-2 tw-bg-white tw-border-t tw-border-gray-200 tw-sticky tw-bottom-0 tw-z-10\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || userMasterForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n Save User Master\n </button>\n </div>\n </form>\n</div>\n\n<!-- Template Renderers for Role Permissions Grid -->\n<ng-template #menuDetailsRendererTemplate let-row=\"row\">\n <div class=\"tw-flex tw-items-center tw-space-x-3 tw-min-w-0\">\n <!-- Menu Icon -->\n <div class=\"tw-flex-shrink-0\">\n @if (row.syme_type === 'module') {\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-4 tw-h-4\">folder</cide-ele-icon>\n } @else if (row.syme_type === 'section') {\n <cide-ele-icon class=\"tw-text-green-600 tw-w-4 tw-h-4\">folder_open</cide-ele-icon>\n } @else if (row.syme_type === 'menu') {\n <cide-ele-icon class=\"tw-text-purple-600 tw-w-4 tw-h-4\">menu</cide-ele-icon>\n } @else {\n <cide-ele-icon class=\"tw-text-gray-600 tw-w-4 tw-h-4\">description</cide-ele-icon>\n }\n </div>\n\n <!-- Menu Details -->\n <div class=\"tw-ml-3 tw-min-w-0 tw-flex-1\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-text-xs tw-font-medium tw-text-gray-900 tw-truncate\" [title]=\"row.syme_title\">\n {{ row.syme_title || row.menu?.syme_title || row.menu?.syme_menu_name || 'Untitled' }}\n </div>\n <!-- Green pill indicator for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800 tw-whitespace-nowrap\">\n Assigned\n </span>\n }\n }\n </div>\n @if (row.permission?.sygms_name) {\n <div class=\"tw-text-xs tw-text-blue-500 tw-truncate\" [title]=\"row.permission?.sygms_name\">\n {{ row.permission?.sygms_name }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Menu Type Renderer Template -->\n<ng-template #menuTypeRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-items-center tw-justify-center\">\n @if (row.syme_type === 'module') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-blue-100 tw-text-blue-800\">\n Module\n </span>\n } @else if (row.syme_type === 'section') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n Section\n </span>\n } @else if (row.syme_type === 'menu') {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-purple-100 tw-text-purple-800\">\n Menu\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-gray-100 tw-text-gray-800\">\n {{ row.syme_type || 'Unknown' }}\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Checkbox Renderer Template -->\n<ng-template #permissionsCheckboxRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row.syme_type === 'menu' && row?.syme_permissions_id_sygms && row?.syme_permissions_id_sygms.length > 0) {\n @for (permissionId of row?.syme_permissions_id_sygms || []; track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <div class=\"tw-flex tw-items-center tw-space-x-1\">\n <input type=\"checkbox\" [checked]=\"isPermissionSelected(row._id, permissionId)\" [disabled]=\"true\"\n class=\"tw-h-4 tw-w-4 tw-text-blue-600 tw-bg-gray-100 tw-border-gray-300 tw-rounded focus:tw-ring-blue-500\">\n <label class=\"tw-text-xs tw-text-gray-700\">\n {{ getPermissionById(permissionId)?.sygms_name || 'Unknown' }}\n </label>\n </div>\n </div>\n }\n } @else {\n <!-- Show green checkmark for parent menus with child permissions -->\n @if (row.syme_type === 'module' || row.syme_type === 'section' || row.syme_type === 'title') {\n @if (hasChildMenusWithPermissions(row._id)) {\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-green-100 tw-rounded-full\">\n <cide-ele-icon class=\"tw-text-green-600\" size=\"xs\">\n check\n </cide-ele-icon>\n </div>\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">N/A</span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Menu Rights Permissions Renderer Template -->\n<ng-template #menuRightsPermissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n <!-- Role Rights Display -->\n @if (row.role_rights && row.role_rights.length > 0) {\n <div class=\"tw-mb-2\">\n <div class=\"tw-text-xs tw-text-gray-500 tw-mb-1\">Role Rights:</div>\n <div class=\"tw-flex tw-flex-wrap tw-gap-1\">\n @for (right of row.role_rights; track $index) {\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-blue-100 tw-text-blue-800 tw-rounded\">\n {{ right }}\n </span>\n }\n </div>\n </div>\n }\n\n\n <!-- Exception Indicator -->\n @if (row.hasException) {\n <div class=\"tw-mt-2\">\n <span class=\"tw-inline-block tw-px-2 tw-py-1 tw-text-xs tw-bg-yellow-100 tw-text-yellow-800 tw-rounded\">\n Override\n </span>\n </div>\n } @else {\n <div class=\"tw-mt-2\">\n <span class=\"tw-text-xs tw-text-gray-400\">Default</span>\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Permissions Renderer Template -->\n<ng-template #permissionsRendererTemplate let-row=\"row\" let-value=\"value\">\n <div class=\"tw-flex tw-flex-wrap tw-gap-2 tw-max-w-full\">\n @if (row._permissionValues && Object.keys(row._permissionValues).length > 0) {\n @for (permissionId of Object.keys(row._permissionValues); track permissionId) {\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-input type=\"checkbox\" [ngModel]=\"row._permissionValues[permissionId].checked\"\n (ngModelChange)=\"onPermissionChangeSafe($event, row, permissionId)\"\n [id]=\"'permission-' + row._id + '-' + permissionId\" class=\"tw-h-4 tw-w-4\">\n </cide-ele-input>\n <label [for]=\"'permission-' + row._id + '-' + permissionId\" class=\"tw-text-xs tw-text-gray-700 tw-cursor-pointer\">\n {{ row._permissionValues[permissionId].permission?.sygms_title }}\n </label>\n </div>\n }\n } @else {\n <span class=\"tw-text-xs tw-text-gray-400\">No permissions</span>\n }\n </div>\n</ng-template>" }]
13364
14182
  }], ctorParameters: () => [] });
13365
14183
 
13366
14184
  var userCreate_component = /*#__PURE__*/Object.freeze({
@@ -13871,7 +14689,7 @@ class CideCoreUserListComponent {
13871
14689
  }
13872
14690
  }
13873
14691
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13874
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreUserListComponent, isStandalone: true, selector: "cide-core-user-list", viewQueries: [{ propertyName: "gridComponent", first: true, predicate: CideEleDataGridComponent, descendants: true }, { propertyName: "actionsTemplate", first: true, predicate: ["actionsTemplate"], descendants: true, static: true }, { propertyName: "userDetailsTemplate", first: true, predicate: ["userDetailsTemplate"], descendants: true, static: true }, { propertyName: "contactInfoTemplate", first: true, predicate: ["contactInfoTemplate"], descendants: true, static: true }, { propertyName: "organizationTemplate", first: true, predicate: ["organizationTemplate"], descendants: true, static: true }, { propertyName: "validityTemplate", first: true, predicate: ["validityTemplate"], descendants: true, static: true }, { propertyName: "statusTemplate", first: true, predicate: ["statusTemplate"], descendants: true, static: true }], ngImport: i0, template: "<!-- User Master List Container -->\n<div class=\"user-master-listing-container tw-bg-white tw-shadow-lg tw-rounded-lg tw-table tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-4 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600\">people</cide-ele-icon>\n <div>\n <h5 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">User Master Management</h5>\n <p class=\"tw-text-sm tw-text-gray-600\">Manage and view all user master records in the system</p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <!-- Status Filter -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <label for=\"statusFilter\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Status:</label>\n <cide-ele-select id=\"statusFilter\" [options]=\"statusFilterOptions()\" [(ngModel)]=\"selectedStatusFilterValue\"\n (ngModelChange)=\"onFilterChange()\" class=\"tw-min-w-40\">\n </cide-ele-select>\n </div>\n\n <!-- Add User Button -->\n <button cideEleButton variant=\"primary\" size=\"sm\" (click)=\"onAddUser()\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-6 tw-h-5\">add</cide-ele-icon>\n Add User\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex\">\n <cide-ele-icon name=\"exclamation-triangle\" class=\"tw-text-red-400\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n <div class=\"tw-h-full tw-overflow-auto\">\n <!-- Data Grid Component -->\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers\"\n [serverSidePagination]=\"true\" [totalServerItems]=\"totalItems()\" [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n </div>\n </div>\n\n</div>\n\n<!-- Template Definitions for Grid Renderers -->\n\n<!-- User Details Template -->\n<ng-template #userDetailsTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <div\n class=\"tw-flex-shrink-0 tw-w-12 tw-h-12 tw-bg-blue-100 tw-rounded-full tw-flex tw-items-center tw-justify-center\">\n <span class=\"tw-text-blue-600 tw-font-semibold tw-text-sm\">\n {{ getUserInitials(row.user_firstname, row.user_lastname) }}\n </span>\n </div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <p class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-truncate\" [title]=\"row.user_fullname\">\n {{ row.user_fullname || 'Unknown User' }}\n </p>\n <p class=\"tw-text-xs tw-text-blue-600 tw-truncate tw-font-medium\" [title]=\"'Username: ' + row.user_username\">\n @{{ row.user_username || 'No username' }}\n </p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-truncate\" [title]=\"'ID: ' + row._id\">\n ID: {{ row._id?.substring(0, 8) }}...\n </p>\n </div>\n </div>\n</ng-template>\n\n<!-- Contact Info Template -->\n<ng-template #contactInfoTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-flex tw-items-center\" [title]=\"'Email: ' + row.user_emailid\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z\" />\n <path d=\"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_emailid || 'No email' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-600 tw-flex tw-items-center\" [title]=\"'Mobile: ' + row.user_mobileno\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n d=\"M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_mobileno || 'No mobile' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-500 tw-flex tw-items-center\"\n [title]=\"'Password Change: ' + getPasswordChangeText(row.user_passwordchangeonlogin)\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\"\n d=\"M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z\"\n clip-rule=\"evenodd\" />\n </svg>\n <span class=\"tw-truncate\">{{ getPasswordChangeText(row.user_passwordchangeonlogin) }}</span>\n </p>\n </div>\n</ng-template>\n\n\n\n<!-- Validity Template -->\n<ng-template #validityTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-text-center tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-font-medium\">\n Validity managed per entity\n </p>\n <p class=\"tw-text-xs tw-text-gray-600\">\n Check entity mappings for details\n </p>\n </div>\n</ng-template>\n\n<!-- Status Template -->\n<ng-template #statusTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-justify-center\">\n @if (row.user_isactive) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Inactive\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Actions Template using cide-ele-dropdown -->\n<ng-template #actionsTemplate let-value let-row=\"row\" let-column=\"column\">\n <cide-ele-dropdown [items]=\"getDropdownItems(row)\" [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm', usePortal: true, minWidth: 200 }\" (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>", styles: [".user-master-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
14692
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreUserListComponent, isStandalone: true, selector: "cide-core-user-list", viewQueries: [{ propertyName: "gridComponent", first: true, predicate: CideEleDataGridComponent, descendants: true }, { propertyName: "actionsTemplate", first: true, predicate: ["actionsTemplate"], descendants: true, static: true }, { propertyName: "userDetailsTemplate", first: true, predicate: ["userDetailsTemplate"], descendants: true, static: true }, { propertyName: "contactInfoTemplate", first: true, predicate: ["contactInfoTemplate"], descendants: true, static: true }, { propertyName: "organizationTemplate", first: true, predicate: ["organizationTemplate"], descendants: true, static: true }, { propertyName: "validityTemplate", first: true, predicate: ["validityTemplate"], descendants: true, static: true }, { propertyName: "statusTemplate", first: true, predicate: ["statusTemplate"], descendants: true, static: true }], ngImport: i0, template: "<!-- User Master List Container -->\n<div class=\"user-master-listing-container tw-bg-white tw-shadow-lg tw-rounded-lg tw-table tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-4 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\"> \n <cide-ele-icon class=\"tw-text-blue-600\">people</cide-ele-icon>\n <div>\n <h5 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">User Master Management</h5>\n <p class=\"tw-text-sm tw-text-gray-600\">Manage and view all user master records in the system</p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <!-- Status Filter -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <label for=\"statusFilter\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Status:</label>\n <cide-ele-select id=\"statusFilter\" [options]=\"statusFilterOptions()\" [(ngModel)]=\"selectedStatusFilterValue\"\n (ngModelChange)=\"onFilterChange()\" class=\"tw-min-w-40\">\n </cide-ele-select>\n </div>\n\n <!-- Add User Button -->\n <button cideEleButton variant=\"primary\" size=\"sm\" (click)=\"onAddUser()\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-6 tw-h-5\">add</cide-ele-icon>\n Add User\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex\">\n <cide-ele-icon name=\"exclamation-triangle\" class=\"tw-text-red-400\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n <div class=\"tw-h-full tw-overflow-auto\">\n <!-- Data Grid Component -->\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers\"\n [serverSidePagination]=\"true\" [totalServerItems]=\"totalItems()\" [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n </div>\n </div>\n\n</div>\n\n<!-- Template Definitions for Grid Renderers -->\n\n<!-- User Details Template -->\n<ng-template #userDetailsTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <div\n class=\"tw-flex-shrink-0 tw-w-12 tw-h-12 tw-bg-blue-100 tw-rounded-full tw-flex tw-items-center tw-justify-center\">\n <span class=\"tw-text-blue-600 tw-font-semibold tw-text-sm\">\n {{ getUserInitials(row.user_firstname, row.user_lastname) }}\n </span>\n </div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <p class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-truncate\" [title]=\"row.user_fullname\">\n {{ row.user_fullname || 'Unknown User' }}\n </p>\n <p class=\"tw-text-xs tw-text-blue-600 tw-truncate tw-font-medium\" [title]=\"'Username: ' + row.user_username\">\n @{{ row.user_username || 'No username' }}\n </p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-truncate\" [title]=\"'ID: ' + row._id\">\n ID: {{ row._id?.substring(0, 8) }}...\n </p>\n </div>\n </div>\n</ng-template>\n\n<!-- Contact Info Template -->\n<ng-template #contactInfoTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-flex tw-items-center\" [title]=\"'Email: ' + row.user_emailid\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z\" />\n <path d=\"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_emailid || 'No email' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-600 tw-flex tw-items-center\" [title]=\"'Mobile: ' + row.user_mobileno\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n d=\"M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_mobileno || 'No mobile' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-500 tw-flex tw-items-center\"\n [title]=\"'Password Change: ' + getPasswordChangeText(row.user_passwordchangeonlogin)\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\"\n d=\"M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z\"\n clip-rule=\"evenodd\" />\n </svg>\n <span class=\"tw-truncate\">{{ getPasswordChangeText(row.user_passwordchangeonlogin) }}</span>\n </p>\n </div>\n</ng-template>\n\n\n\n<!-- Validity Template -->\n<ng-template #validityTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-text-center tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-font-medium\">\n Validity managed per entity\n </p>\n <p class=\"tw-text-xs tw-text-gray-600\">\n Check entity mappings for details\n </p>\n </div>\n</ng-template>\n\n<!-- Status Template -->\n<ng-template #statusTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-justify-center\">\n @if (row.user_isactive) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Inactive\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Actions Template using cide-ele-dropdown -->\n<ng-template #actionsTemplate let-value let-row=\"row\" let-column=\"column\">\n <cide-ele-dropdown [items]=\"getDropdownItems(row)\" [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm', usePortal: true, minWidth: 200 }\" (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>", styles: [".user-master-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
13875
14693
  }
13876
14694
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserListComponent, decorators: [{
13877
14695
  type: Component,
@@ -13883,7 +14701,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
13883
14701
  CideSelectComponent,
13884
14702
  CideEleDataGridComponent,
13885
14703
  CideEleDropdownComponent
13886
- ], template: "<!-- User Master List Container -->\n<div class=\"user-master-listing-container tw-bg-white tw-shadow-lg tw-rounded-lg tw-table tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-4 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <cide-ele-icon class=\"tw-text-blue-600\">people</cide-ele-icon>\n <div>\n <h5 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">User Master Management</h5>\n <p class=\"tw-text-sm tw-text-gray-600\">Manage and view all user master records in the system</p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <!-- Status Filter -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <label for=\"statusFilter\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Status:</label>\n <cide-ele-select id=\"statusFilter\" [options]=\"statusFilterOptions()\" [(ngModel)]=\"selectedStatusFilterValue\"\n (ngModelChange)=\"onFilterChange()\" class=\"tw-min-w-40\">\n </cide-ele-select>\n </div>\n\n <!-- Add User Button -->\n <button cideEleButton variant=\"primary\" size=\"sm\" (click)=\"onAddUser()\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-6 tw-h-5\">add</cide-ele-icon>\n Add User\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex\">\n <cide-ele-icon name=\"exclamation-triangle\" class=\"tw-text-red-400\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n <div class=\"tw-h-full tw-overflow-auto\">\n <!-- Data Grid Component -->\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers\"\n [serverSidePagination]=\"true\" [totalServerItems]=\"totalItems()\" [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n </div>\n </div>\n\n</div>\n\n<!-- Template Definitions for Grid Renderers -->\n\n<!-- User Details Template -->\n<ng-template #userDetailsTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <div\n class=\"tw-flex-shrink-0 tw-w-12 tw-h-12 tw-bg-blue-100 tw-rounded-full tw-flex tw-items-center tw-justify-center\">\n <span class=\"tw-text-blue-600 tw-font-semibold tw-text-sm\">\n {{ getUserInitials(row.user_firstname, row.user_lastname) }}\n </span>\n </div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <p class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-truncate\" [title]=\"row.user_fullname\">\n {{ row.user_fullname || 'Unknown User' }}\n </p>\n <p class=\"tw-text-xs tw-text-blue-600 tw-truncate tw-font-medium\" [title]=\"'Username: ' + row.user_username\">\n @{{ row.user_username || 'No username' }}\n </p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-truncate\" [title]=\"'ID: ' + row._id\">\n ID: {{ row._id?.substring(0, 8) }}...\n </p>\n </div>\n </div>\n</ng-template>\n\n<!-- Contact Info Template -->\n<ng-template #contactInfoTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-flex tw-items-center\" [title]=\"'Email: ' + row.user_emailid\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z\" />\n <path d=\"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_emailid || 'No email' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-600 tw-flex tw-items-center\" [title]=\"'Mobile: ' + row.user_mobileno\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n d=\"M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_mobileno || 'No mobile' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-500 tw-flex tw-items-center\"\n [title]=\"'Password Change: ' + getPasswordChangeText(row.user_passwordchangeonlogin)\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\"\n d=\"M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z\"\n clip-rule=\"evenodd\" />\n </svg>\n <span class=\"tw-truncate\">{{ getPasswordChangeText(row.user_passwordchangeonlogin) }}</span>\n </p>\n </div>\n</ng-template>\n\n\n\n<!-- Validity Template -->\n<ng-template #validityTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-text-center tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-font-medium\">\n Validity managed per entity\n </p>\n <p class=\"tw-text-xs tw-text-gray-600\">\n Check entity mappings for details\n </p>\n </div>\n</ng-template>\n\n<!-- Status Template -->\n<ng-template #statusTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-justify-center\">\n @if (row.user_isactive) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Inactive\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Actions Template using cide-ele-dropdown -->\n<ng-template #actionsTemplate let-value let-row=\"row\" let-column=\"column\">\n <cide-ele-dropdown [items]=\"getDropdownItems(row)\" [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm', usePortal: true, minWidth: 200 }\" (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>", styles: [".user-master-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"] }]
14704
+ ], template: "<!-- User Master List Container -->\n<div class=\"user-master-listing-container tw-bg-white tw-shadow-lg tw-rounded-lg tw-table tw-h-full\">\n\n <!-- Header Section with Filters -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-px-6 tw-py-4 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-4 sm:tw-space-y-0\">\n\n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\"> \n <cide-ele-icon class=\"tw-text-blue-600\">people</cide-ele-icon>\n <div>\n <h5 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">User Master Management</h5>\n <p class=\"tw-text-sm tw-text-gray-600\">Manage and view all user master records in the system</p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <!-- Status Filter -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <label for=\"statusFilter\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Status:</label>\n <cide-ele-select id=\"statusFilter\" [options]=\"statusFilterOptions()\" [(ngModel)]=\"selectedStatusFilterValue\"\n (ngModelChange)=\"onFilterChange()\" class=\"tw-min-w-40\">\n </cide-ele-select>\n </div>\n\n <!-- Add User Button -->\n <button cideEleButton variant=\"primary\" size=\"sm\" (click)=\"onAddUser()\"\n class=\"tw-whitespace-nowrap tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon size=\"xs\" class=\"tw-w-6 tw-h-5\">add</cide-ele-icon>\n Add User\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n @if (error()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\n <div class=\"tw-flex\">\n <cide-ele-icon name=\"exclamation-triangle\" class=\"tw-text-red-400\"></cide-ele-icon>\n <div class=\"tw-ml-3\">\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800\">Error</h3>\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1\">{{ error() }}</p>\n </div>\n </div>\n </div>\n }\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-h-full tw-relative\">\n <div class=\"tw-h-full tw-overflow-auto\">\n <!-- Data Grid Component -->\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers\"\n [serverSidePagination]=\"true\" [totalServerItems]=\"totalItems()\" [currentServerPage]=\"currentPage()\"\n [currentServerPageSize]=\"pageSize()\" (gridEvent)=\"onGridEvent($event)\">\n </cide-ele-data-grid>\n </div>\n </div>\n </div>\n\n</div>\n\n<!-- Template Definitions for Grid Renderers -->\n\n<!-- User Details Template -->\n<ng-template #userDetailsTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-items-center tw-space-x-3\">\n <div\n class=\"tw-flex-shrink-0 tw-w-12 tw-h-12 tw-bg-blue-100 tw-rounded-full tw-flex tw-items-center tw-justify-center\">\n <span class=\"tw-text-blue-600 tw-font-semibold tw-text-sm\">\n {{ getUserInitials(row.user_firstname, row.user_lastname) }}\n </span>\n </div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <p class=\"tw-text-sm tw-font-semibold tw-text-gray-900 tw-truncate\" [title]=\"row.user_fullname\">\n {{ row.user_fullname || 'Unknown User' }}\n </p>\n <p class=\"tw-text-xs tw-text-blue-600 tw-truncate tw-font-medium\" [title]=\"'Username: ' + row.user_username\">\n @{{ row.user_username || 'No username' }}\n </p>\n <p class=\"tw-text-xs tw-text-gray-400 tw-truncate\" [title]=\"'ID: ' + row._id\">\n ID: {{ row._id?.substring(0, 8) }}...\n </p>\n </div>\n </div>\n</ng-template>\n\n<!-- Contact Info Template -->\n<ng-template #contactInfoTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-flex tw-items-center\" [title]=\"'Email: ' + row.user_emailid\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z\" />\n <path d=\"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_emailid || 'No email' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-600 tw-flex tw-items-center\" [title]=\"'Mobile: ' + row.user_mobileno\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n d=\"M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z\" />\n </svg>\n <span class=\"tw-truncate\">{{ row.user_mobileno || 'No mobile' }}</span>\n </p>\n <p class=\"tw-text-xs tw-text-gray-500 tw-flex tw-items-center\"\n [title]=\"'Password Change: ' + getPasswordChangeText(row.user_passwordchangeonlogin)\">\n <svg class=\"tw-flex-shrink-0 tw-w-3 tw-h-3 tw-text-gray-400 tw-mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\"\n d=\"M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z\"\n clip-rule=\"evenodd\" />\n </svg>\n <span class=\"tw-truncate\">{{ getPasswordChangeText(row.user_passwordchangeonlogin) }}</span>\n </p>\n </div>\n</ng-template>\n\n\n\n<!-- Validity Template -->\n<ng-template #validityTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-text-center tw-space-y-1\">\n <p class=\"tw-text-xs tw-text-gray-900 tw-font-medium\">\n Validity managed per entity\n </p>\n <p class=\"tw-text-xs tw-text-gray-600\">\n Check entity mappings for details\n </p>\n </div>\n</ng-template>\n\n<!-- Status Template -->\n<ng-template #statusTemplate let-value let-row=\"row\" let-column=\"column\">\n <div class=\"tw-flex tw-justify-center\">\n @if (row.user_isactive) {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-green-100 tw-text-green-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Active\n </span>\n } @else {\n <span\n class=\"tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800\">\n <svg class=\"tw-w-1.5 tw-h-1.5 tw-mr-1\" fill=\"currentColor\" viewBox=\"0 0 8 8\">\n <circle cx=\"4\" cy=\"4\" r=\"3\" />\n </svg>\n Inactive\n </span>\n }\n </div>\n</ng-template>\n\n<!-- Actions Template using cide-ele-dropdown -->\n<ng-template #actionsTemplate let-value let-row=\"row\" let-column=\"column\">\n <cide-ele-dropdown [items]=\"getDropdownItems(row)\" [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm', usePortal: true, minWidth: 200 }\" (itemClick)=\"onDropdownItemClick($event, row)\">\n </cide-ele-dropdown>\n</ng-template>", styles: [".user-master-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"] }]
13887
14705
  }], propDecorators: { gridComponent: [{
13888
14706
  type: ViewChild,
13889
14707
  args: [CideEleDataGridComponent]