cloud-ide-core 2.0.6 → 2.0.8

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, CideEleFloatingFeaturesService, CideEleToastNotificationComponent } from 'cloud-ide-element';
16
+ import { AppStateHelperService, CideLytFloatingEntityRightsSharingService } 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", "showFloatingUploader", "floatingUploaderGroupId"], 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({
@@ -10398,7 +10484,7 @@ class CideCoreEntityCreateComponent {
10398
10484
  };
10399
10485
  }
10400
10486
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreEntityCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10401
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreEntityCreateComponent, isStandalone: true, selector: "cide-core-entity-create", ngImport: i0, template: "<!-- Modern Entity Create Form -->\n<div class=\"tw-min-h-scree\">\n <div class=\"tw-mx-auto\">\n\n\n <form [formGroup]=\"entityForm\" [class.tw-opacity-60]=\"loading()\" [class.tw-pointer-events-none]=\"loading()\"\n (ngSubmit)=\"onSubmit()\" class=\"tw-space-y-6\">\n\n <!-- Basic Information Section -->\n <div class=\"tw-p-4 tw-pb-0\">\n <div class=\"tw-space-y-6\">\n <!-- Top Section: Image on Right, Form Fields on Left -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-6\">\n <!-- Institution Name, Entity Type & Active Status -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[1fr_250px_120px] tw-gap-4 tw-items-end\">\n <cide-ele-input id=\"syen_name\" type=\"text\" label=\"Institution Name *\" formControlName=\"syen_name\"\n placeholder=\"Enter institution name\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Entity Type *\" labelPlacement=\"floating\" [options]=\"entityTypes()\"\n formControlName=\"syen_entity_type_sygms\" placeholder=\"Select institution type\" size=\"sm\">\n </cide-ele-select>\n\n <div class=\"tw-flex tw-items-center tw-justify-center tw-gap-1 tw-h-full\">\n <cide-ele-input type=\"checkbox\" formControlName=\"syen_isactive\" size=\"sm\" label=\"Is Active\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- UDISE, Affiliation & Institution Code -->\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 label=\"UDISE Number\" formControlName=\"syen_udise_no\" placeholder=\"Enter UDISE number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Affiliation Number\" formControlName=\"syen_affiliation_no\"\n placeholder=\"Enter affiliation number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Institution Code *\" formControlName=\"syen_entity_code\"\n placeholder=\"Enter unique code\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Entity Image Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-pt-0\">\n <cide-ele-file-input id=\"entity_image_upload\" formControlName=\"syen_photo_id_cyfm\" accept=\"image/*\"\n [showPreview]=\"true\" [previewBoxMode]=\"true\" [showFileName]=\"false\" \n previewWidth=\"180px\" previewHeight=\"120px\" [required]=\"true\"\n placeholderText=\"Upload Logo\" placeholderIcon=\"cloud_upload\"\n [autoUpload]=\"true\" [uploadData]=\"getUploadData()\"\n (uploadSuccess)=\"onImageUploadSuccess($event)\" \n (uploadError)=\"onImageUploadError($event)\"\n (uploadProgressChange)=\"onImageUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-px-4 !tw-mt-0\">\n <cide-ele-tab [tabs]=\"entityTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-all tw-duration-300 tw-ease-in-out !tw-mt-2\" [class.tw-opacity-60]=\"loading()\"\n [class.tw-pointer-events-none]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('corporate') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Corporate Address - Full Width -->\n <div class=\"tw-w-full\">\n <cide-ele-textarea label=\"Corporate Address *\" formControlName=\"syen_corporate_address\"\n placeholder=\"Enter complete corporate address\" [rows]=\"4\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code & City - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Postal Code\" [options]=\"postalCodes()\" formControlName=\"syen_corporate_pin_sypin\"\n placeholder=\"Select postal code\" [searchable]=\"true\" [loading]=\"postalCodesLoading()\"\n (searchChange)=\"onPostalCodeSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-input label=\"City\" formControlName=\"syen_corporate_city_sypin\" placeholder=\"Enter city name\">\n </cide-ele-input>\n </div>\n \n <!-- State & Country - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"State\" formControlName=\"syen_corporate_state_sypin\" placeholder=\"Enter state name\">\n </cide-ele-input>\n \n <cide-ele-select label=\"Country\" [options]=\"corporateCountries()\"\n formControlName=\"syen_corporate_country_syctr\" placeholder=\"Select country\" [searchable]=\"true\"\n (searchChange)=\"onCorporateCountrySearch($event)\" [loading]=\"corporateCountriesLoading()\">\n </cide-ele-select>\n </div>\n </div>\n </div>\n }\n\n @case ('contact') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Contact Person & Currency - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Primary Contact Person\" [options]=\"users()\"\n formControlName=\"syen_corporate_contact_person_user\" placeholder=\"Select contact person\"\n [searchable]=\"true\" [loading]=\"usersLoading()\" (searchChange)=\"onUserSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-select label=\"Currency\" [options]=\"currencies()\" formControlName=\"syen_currency_sycr\"\n placeholder=\"Select currency\">\n </cide-ele-select>\n </div>\n \n <!-- Phone Numbers - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Primary Phone *\" formControlName=\"syen_corporate_phone\" type=\"tel\"\n placeholder=\"Enter primary phone number\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Alternate Phone\" formControlName=\"syen_corporate_phone_alt\" type=\"tel\"\n placeholder=\"Enter alternate phone number\">\n </cide-ele-input>\n </div>\n \n <!-- Fax & Website - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Fax Number\" id=\"syen_corporate_fax\" formControlName=\"syen_corporate_fax\" placeholder=\"Enter fax number\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Website URL\" formControlName=\"syen_website\" type=\"url\"\n placeholder=\"https://example.com\" autocomplete=\"url\" leadingIcon=\"language\"\n helperText=\"Enter a valid website URL starting with http:// or https://\">\n </cide-ele-input>\n </div>\n \n <!-- Email Addresses - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Primary Email *\" formControlName=\"syen_corporate_email\" type=\"email\"\n placeholder=\"Enter primary email address\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Alternate Email\" formControlName=\"syen_corporate_email_alt\" type=\"email\"\n placeholder=\"Enter alternate email address\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n\n @case ('registered') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Registered Address - Full Width -->\n <div class=\"tw-w-full\">\n <cide-ele-textarea label=\"Registered Address *\" formControlName=\"syen_registered_address\"\n placeholder=\"Enter complete registered address\" [rows]=\"4\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code, City, State & Country - Four Columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[220px_0.8fr_0.7fr_240px] tw-gap-6\">\n <cide-ele-select label=\"Postal Code\" [options]=\"postalCodes()\" formControlName=\"syen_registered_pin_sypin\"\n placeholder=\"Select postal code\" [searchable]=\"true\" [loading]=\"postalCodesLoading()\"\n (searchChange)=\"onPostalCodeSearch($event)\" size=\"sm\">\n </cide-ele-select>\n \n <cide-ele-input label=\"City\" formControlName=\"syen_registered_city_sypin\" placeholder=\"Enter city name\">\n </cide-ele-input>\n \n <cide-ele-input label=\"State\" formControlName=\"syen_registered_state_sypin\"\n placeholder=\"Enter state name\">\n </cide-ele-input>\n \n <cide-ele-select label=\"Country\" [options]=\"registeredCountries()\"\n formControlName=\"syen_registered_country_syctr\" placeholder=\"Select country\" [searchable]=\"true\"\n (searchChange)=\"onRegisteredCountrySearch($event)\" [loading]=\"registeredCountriesLoading()\" size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Contact Person, Phone, Email & Fax - Four Columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[1fr_200px_1fr_150px] tw-gap-6\">\n <cide-ele-select label=\"Contact Person\" [options]=\"users()\"\n formControlName=\"syen_registered_contact_person_user\" placeholder=\"Select contact person\"\n [searchable]=\"true\" [loading]=\"usersLoading()\" (searchChange)=\"onUserSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-input label=\"Phone\" formControlName=\"syen_registered_phone\" type=\"tel\"\n placeholder=\"Enter phone number\" size=\"sm\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Email\" formControlName=\"syen_registered_email\" type=\"email\"\n placeholder=\"Enter email address\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Fax\" formControlName=\"syen_registered_fax\" placeholder=\"Enter fax number\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n\n }\n </div>\n\n <!-- Form Actions -->\n <div class=\"tw-p-4\">\n <div class=\"tw-flex tw-justify-end tw-gap-3\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"md\" (click)=\"onReset()\" [disabled]=\"loading()\">\n <cide-ele-icon>refresh</cide-ele-icon>\n Reset Form\n </button>\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"md\" [disabled]=\"loading() || entityForm.invalid\"\n [loading]=\"loading()\">\n <cide-ele-icon>{{ isEditMode() ? 'save' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update Entity' : 'Create Entity' }}\n </button>\n </div>\n </div>\n </form>\n</div>\n</div>", styles: [""], dependencies: [{ 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: "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: 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: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { 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: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
10487
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideCoreEntityCreateComponent, isStandalone: true, selector: "cide-core-entity-create", ngImport: i0, template: "<!-- Modern Entity Create Form -->\n<div class=\"tw-min-h-scree\">\n <div class=\"tw-mx-auto\">\n\n\n <form [formGroup]=\"entityForm\" [class.tw-opacity-60]=\"loading()\" [class.tw-pointer-events-none]=\"loading()\"\n (ngSubmit)=\"onSubmit()\" class=\"tw-space-y-6\">\n\n <!-- Basic Information Section -->\n <div class=\"tw-p-4 tw-pb-0\">\n <div class=\"tw-space-y-6\">\n <!-- Top Section: Image on Right, Form Fields on Left -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-[1fr_200px] tw-gap-4\">\n <!-- Left Side: Form Fields -->\n <div class=\"tw-space-y-6\">\n <!-- Institution Name, Entity Type & Active Status -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[1fr_250px_120px] tw-gap-4 tw-items-end\">\n <cide-ele-input id=\"syen_name\" type=\"text\" label=\"Institution Name *\" formControlName=\"syen_name\"\n placeholder=\"Enter institution name\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-select label=\"Entity Type *\" labelPlacement=\"floating\" [options]=\"entityTypes()\"\n formControlName=\"syen_entity_type_sygms\" placeholder=\"Select institution type\" size=\"sm\">\n </cide-ele-select>\n\n <div class=\"tw-flex tw-items-center tw-justify-center tw-gap-1 tw-h-full\">\n <cide-ele-input type=\"checkbox\" formControlName=\"syen_isactive\" size=\"sm\" label=\"Is Active\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- UDISE, Affiliation & Institution Code -->\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 label=\"UDISE Number\" formControlName=\"syen_udise_no\" placeholder=\"Enter UDISE number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Affiliation Number\" formControlName=\"syen_affiliation_no\"\n placeholder=\"Enter affiliation number\" size=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Institution Code *\" formControlName=\"syen_entity_code\"\n placeholder=\"Enter unique code\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n\n <!-- Right Side: Entity Image Upload -->\n <div class=\"tw-flex tw-items-start tw-justify-center tw-pt-0\">\n <cide-ele-file-input id=\"entity_image_upload\" formControlName=\"syen_photo_id_cyfm\" accept=\"image/*\"\n [showPreview]=\"true\" [previewBoxMode]=\"true\" [showFileName]=\"false\" \n previewWidth=\"180px\" previewHeight=\"120px\" [required]=\"true\"\n placeholderText=\"Upload Logo\" placeholderIcon=\"cloud_upload\"\n [autoUpload]=\"true\" [uploadData]=\"getUploadData()\"\n (uploadSuccess)=\"onImageUploadSuccess($event)\" \n (uploadError)=\"onImageUploadError($event)\"\n (uploadProgressChange)=\"onImageUploadProgress($event)\">\n </cide-ele-file-input>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-px-4 !tw-mt-0\">\n <cide-ele-tab [tabs]=\"entityTabs()\" [activeTabId]=\"activeTab()\" size=\"sm\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-transition-all tw-duration-300 tw-ease-in-out !tw-mt-2\" [class.tw-opacity-60]=\"loading()\"\n [class.tw-pointer-events-none]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('corporate') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Corporate Address - Full Width -->\n <div class=\"tw-w-full\">\n <cide-ele-textarea label=\"Corporate Address *\" formControlName=\"syen_corporate_address\"\n placeholder=\"Enter complete corporate address\" [rows]=\"4\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code & City - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Postal Code\" [options]=\"postalCodes()\" formControlName=\"syen_corporate_pin_sypin\"\n placeholder=\"Select postal code\" [searchable]=\"true\" [loading]=\"postalCodesLoading()\"\n (searchChange)=\"onPostalCodeSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-input label=\"City\" formControlName=\"syen_corporate_city_sypin\" placeholder=\"Enter city name\">\n </cide-ele-input>\n </div>\n \n <!-- State & Country - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"State\" formControlName=\"syen_corporate_state_sypin\" placeholder=\"Enter state name\">\n </cide-ele-input>\n \n <cide-ele-select label=\"Country\" [options]=\"corporateCountries()\"\n formControlName=\"syen_corporate_country_syctr\" placeholder=\"Select country\" [searchable]=\"true\"\n (searchChange)=\"onCorporateCountrySearch($event)\" [loading]=\"corporateCountriesLoading()\">\n </cide-ele-select>\n </div>\n </div>\n </div>\n }\n\n @case ('contact') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Contact Person & Currency - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-select label=\"Primary Contact Person\" [options]=\"users()\"\n formControlName=\"syen_corporate_contact_person_user\" placeholder=\"Select contact person\"\n [searchable]=\"true\" [loading]=\"usersLoading()\" (searchChange)=\"onUserSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-select label=\"Currency\" [options]=\"currencies()\" formControlName=\"syen_currency_sycr\"\n placeholder=\"Select currency\">\n </cide-ele-select>\n </div>\n \n <!-- Phone Numbers - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Primary Phone *\" formControlName=\"syen_corporate_phone\" type=\"tel\"\n placeholder=\"Enter primary phone number\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Alternate Phone\" formControlName=\"syen_corporate_phone_alt\" type=\"tel\"\n placeholder=\"Enter alternate phone number\">\n </cide-ele-input>\n </div>\n \n <!-- Fax & Website - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Fax Number\" id=\"syen_corporate_fax\" formControlName=\"syen_corporate_fax\" placeholder=\"Enter fax number\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Website URL\" formControlName=\"syen_website\" type=\"url\"\n placeholder=\"https://example.com\" autocomplete=\"url\" leadingIcon=\"language\"\n helperText=\"Enter a valid website URL starting with http:// or https://\">\n </cide-ele-input>\n </div>\n \n <!-- Email Addresses - Two Columns -->\n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Primary Email *\" formControlName=\"syen_corporate_email\" type=\"email\"\n placeholder=\"Enter primary email address\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Alternate Email\" formControlName=\"syen_corporate_email_alt\" type=\"email\"\n placeholder=\"Enter alternate email address\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n\n @case ('registered') {\n <div class=\"tw-p-4\">\n <div class=\"tw-space-y-6\">\n <!-- Registered Address - Full Width -->\n <div class=\"tw-w-full\">\n <cide-ele-textarea label=\"Registered Address *\" formControlName=\"syen_registered_address\"\n placeholder=\"Enter complete registered address\" [rows]=\"4\">\n </cide-ele-textarea>\n </div>\n\n <!-- Postal Code, City, State & Country - Four Columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[220px_0.8fr_0.7fr_240px] tw-gap-6\">\n <cide-ele-select label=\"Postal Code\" [options]=\"postalCodes()\" formControlName=\"syen_registered_pin_sypin\"\n placeholder=\"Select postal code\" [searchable]=\"true\" [loading]=\"postalCodesLoading()\"\n (searchChange)=\"onPostalCodeSearch($event)\" size=\"sm\">\n </cide-ele-select>\n \n <cide-ele-input label=\"City\" formControlName=\"syen_registered_city_sypin\" placeholder=\"Enter city name\">\n </cide-ele-input>\n \n <cide-ele-input label=\"State\" formControlName=\"syen_registered_state_sypin\"\n placeholder=\"Enter state name\">\n </cide-ele-input>\n \n <cide-ele-select label=\"Country\" [options]=\"registeredCountries()\"\n formControlName=\"syen_registered_country_syctr\" placeholder=\"Select country\" [searchable]=\"true\"\n (searchChange)=\"onRegisteredCountrySearch($event)\" [loading]=\"registeredCountriesLoading()\" size=\"sm\">\n </cide-ele-select>\n </div>\n \n <!-- Contact Person, Phone, Email & Fax - Four Columns -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-[1fr_200px_1fr_150px] tw-gap-6\">\n <cide-ele-select label=\"Contact Person\" [options]=\"users()\"\n formControlName=\"syen_registered_contact_person_user\" placeholder=\"Select contact person\"\n [searchable]=\"true\" [loading]=\"usersLoading()\" (searchChange)=\"onUserSearch($event)\">\n </cide-ele-select>\n \n <cide-ele-input label=\"Phone\" formControlName=\"syen_registered_phone\" type=\"tel\"\n placeholder=\"Enter phone number\" size=\"sm\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Email\" formControlName=\"syen_registered_email\" type=\"email\"\n placeholder=\"Enter email address\">\n </cide-ele-input>\n \n <cide-ele-input label=\"Fax\" formControlName=\"syen_registered_fax\" placeholder=\"Enter fax number\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n }\n\n }\n </div>\n\n <!-- Form Actions -->\n <div class=\"tw-p-4\">\n <div class=\"tw-flex tw-justify-end tw-gap-3\">\n <button cideEleButton type=\"button\" variant=\"secondary\" size=\"md\" (click)=\"onReset()\" [disabled]=\"loading()\">\n <cide-ele-icon>refresh</cide-ele-icon>\n Reset Form\n </button>\n \n <button cideEleButton type=\"submit\" variant=\"primary\" size=\"md\" [disabled]=\"loading() || entityForm.invalid\"\n [loading]=\"loading()\">\n <cide-ele-icon>{{ isEditMode() ? 'save' : 'add' }}</cide-ele-icon>\n {{ isEditMode() ? 'Update Entity' : 'Create Entity' }}\n </button>\n </div>\n </div>\n </form>\n</div>\n</div>", styles: [""], dependencies: [{ 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: "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: CideEleFileInputComponent, selector: "cide-ele-file-input", inputs: ["label", "accept", "multiple", "disabled", "required", "helperText", "errorText", "showPreview", "previewWidth", "previewHeight", "previewBoxMode", "showFileName", "placeholderText", "placeholderIcon", "autoUpload", "uploadData", "showFloatingUploader", "floatingUploaderGroupId"], outputs: ["fileChange", "uploadSuccess", "uploadError", "uploadProgressChange"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { 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: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
10402
10488
  }
10403
10489
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreEntityCreateComponent, decorators: [{
10404
10490
  type: Component,
@@ -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
+ floatingFeaturesService = inject(CideEleFloatingFeaturesService);
11109
+ entityRightsService = inject(CideLytFloatingEntityRightsSharingService);
11110
+ notificationService = inject(NotificationService);
11020
11111
  userMasterForm;
11021
11112
  activeTab = signal('basic', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
11022
11113
  loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11023
- error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
11024
11114
  // User information from route
11025
11115
  userId = signal('', ...(ngDevMode ? [{ debugName: "userId" }] : []));
11026
11116
  isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
@@ -11032,6 +11122,119 @@ 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
+ // Entity rights sharing - now using floating service
11129
+ // Template helpers
11130
+ Object = Object;
11131
+ /**
11132
+ * Get address type label for header display
11133
+ */
11134
+ getAddressTypeLabel(addressIndex) {
11135
+ const addressTypeId = this.contactAddressesFormArray.at(addressIndex)?.get('sycad_address_type_id_sygms')?.value;
11136
+ if (addressTypeId) {
11137
+ const addressType = this.addressTypeOptions().find(option => option._id === addressTypeId);
11138
+ return addressType?.sygms_title || 'Address';
11139
+ }
11140
+ return 'Address';
11141
+ }
11142
+ /**
11143
+ * Handle address type change to update header
11144
+ */
11145
+ onAddressTypeChange(addressIndex) {
11146
+ // This method is called when address type changes to trigger header update
11147
+ // The header will automatically update due to change detection
11148
+ }
11149
+ /**
11150
+ * Share address using floating entity rights sharing service
11151
+ */
11152
+ shareAddress(addressIndex) {
11153
+ const address = this.contactAddresses()[addressIndex];
11154
+ if (!address)
11155
+ return;
11156
+ console.log(`📤 Sharing address ${addressIndex}:`, address);
11157
+ // Use the entity rights service
11158
+ this.entityRightsService.show({
11159
+ syepm_access_passs_to: address._id || `address-${addressIndex}`,
11160
+ core_entity_access_pass_management: 'core_user_contact_addresses',
11161
+ syepm_user_id_user: this.appState.getCurrentUser()?._id || ''
11162
+ });
11163
+ }
11164
+ /**
11165
+ * Get document type label for header display
11166
+ */
11167
+ getDocumentTypeLabel(documentIndex) {
11168
+ const documentTypeId = this.documentsFormArray.at(documentIndex)?.get('syusd_document_type_id_sygms')?.value;
11169
+ if (documentTypeId) {
11170
+ const documentType = this.documentTypeOptions().find(option => option._id === documentTypeId);
11171
+ return documentType?.sygms_title || 'Document';
11172
+ }
11173
+ return 'Document';
11174
+ }
11175
+ /**
11176
+ * Handle document type change to update header
11177
+ */
11178
+ onDocumentTypeChange(documentIndex) {
11179
+ // This method is called when document type changes to trigger header update
11180
+ // The header will automatically update due to change detection
11181
+ }
11182
+ /**
11183
+ * Check if user is owner for address sharing
11184
+ */
11185
+ isAddressOwner(addressIndex) {
11186
+ const address = this.contactAddresses()[addressIndex];
11187
+ if (!address)
11188
+ return false;
11189
+ // Check if the address has core_entity_access_pass_management with syepm_is_owner true
11190
+ const accessPassManagement = address.core_entity_access_pass_management;
11191
+ return accessPassManagement?.syepm_is_owner === true;
11192
+ }
11193
+ /**
11194
+ * Handle document files selection
11195
+ */
11196
+ onDocumentFilesSelected(event, documentIndex) {
11197
+ const target = event.target;
11198
+ const files = target.files;
11199
+ if (!files || files.length === 0)
11200
+ return;
11201
+ console.log(`📎 Files selected for document ${documentIndex}:`, files);
11202
+ // Store files in the document form group or handle upload logic here
11203
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
11204
+ if (documentFormGroup) {
11205
+ // You can store the files in a custom property or handle upload immediately
11206
+ // For now, we'll store them in a custom property for display
11207
+ const existingFiles = this.getDocumentFiles(documentIndex);
11208
+ const newFiles = Array.from(files);
11209
+ const allFiles = [...existingFiles, ...newFiles];
11210
+ // Store files in the form group's custom property
11211
+ documentFormGroup._uploadedFiles = allFiles;
11212
+ console.log(`📎 Total files for document ${documentIndex}:`, allFiles.length);
11213
+ }
11214
+ }
11215
+ /**
11216
+ * Get document group ID
11217
+ */
11218
+ getDocumentGroupId(documentIndex) {
11219
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
11220
+ return documentFormGroup?.get('syusd_photo_group_id_cyfm')?.value || '';
11221
+ }
11222
+ /**
11223
+ * Get uploaded files for a document (legacy method for backward compatibility)
11224
+ */
11225
+ getDocumentFiles(documentIndex) {
11226
+ // For multiple file upload with group ID, we don't track individual files
11227
+ // Return empty array since files are managed by group ID
11228
+ return [];
11229
+ }
11230
+ /**
11231
+ * Remove a file from document (legacy method for backward compatibility)
11232
+ */
11233
+ removeDocumentFile(documentIndex, fileName) {
11234
+ // For multiple file upload with group ID, individual file removal is not supported
11235
+ // Files are managed as a group on the server
11236
+ console.log(`📎 Individual file removal not supported for group uploads. Document ${documentIndex}, File: ${fileName}`);
11237
+ }
11035
11238
  constructor() {
11036
11239
  this.userMasterForm = this.fb.group({
11037
11240
  // Basic User Information from auth_user_mst table
@@ -11093,7 +11296,8 @@ class CideCoreUserCreateComponent {
11093
11296
  syenm_activeupto: [''],
11094
11297
  syenm_isdefault: [false],
11095
11298
  syenm_isactive: [true],
11096
- syenm_isloggedin: [true]
11299
+ syenm_isloggedin: [true],
11300
+ exceptions: this.fb.array([]) // Add exceptions FormArray
11097
11301
  });
11098
11302
  }
11099
11303
  // Helper method to create contact address FormGroup
@@ -11116,20 +11320,22 @@ class CideCoreUserCreateComponent {
11116
11320
  }
11117
11321
  // Helper method to create document FormGroup
11118
11322
  createDocumentFormGroup() {
11119
- return this.fb.group({
11323
+ const formGroup = this.fb.group({
11120
11324
  _id: [''],
11325
+ syusd_user_id_user: [''],
11121
11326
  syusd_document_type_id_sygms: [''],
11122
11327
  syusd_doc_number: [''],
11123
11328
  syusd_doc_name_as_per_doc: [''],
11124
- syusd_photo_group_id_cyfm: [''],
11125
11329
  syusd_doc_issue_date: [''],
11126
11330
  syusd_doc_expiry_date: [''],
11331
+ syusd_photo_group_id_cyfm: [''],
11127
11332
  syusd_doc_verification_status_id_sygms: [''],
11128
- syusd_document_kyc_status_id_sygms: [''],
11129
- syusd_document_file_id_cyfm: [''],
11130
- syusd_document_remarks: [''],
11333
+ syusd_doc_kyc_status_id_sygms: [''],
11131
11334
  syusd_isactive: [true]
11132
11335
  });
11336
+ // Initialize file storage for this document
11337
+ formGroup._uploadedFiles = [];
11338
+ return formGroup;
11133
11339
  }
11134
11340
  // Helper method to create family detail FormGroup
11135
11341
  createFamilyDetailFormGroup() {
@@ -11213,7 +11419,7 @@ class CideCoreUserCreateComponent {
11213
11419
  }
11214
11420
  // Handle search change from the select component with debouncing
11215
11421
  onUserSearchChange(searchEvent, familyIndex) {
11216
- const query = searchEvent?.query || searchEvent || '';
11422
+ const query = searchEvent?.query;
11217
11423
  // Clear existing debounce timer for this family member
11218
11424
  if (this.searchDebounceTimers[familyIndex]) {
11219
11425
  clearTimeout(this.searchDebounceTimers[familyIndex]);
@@ -11239,7 +11445,7 @@ class CideCoreUserCreateComponent {
11239
11445
  }
11240
11446
  // Handle user selection change in the form
11241
11447
  onUserSelectionChange(event, familyIndex) {
11242
- const selectedUserId = event?.value || event;
11448
+ const selectedUserId = event?._id;
11243
11449
  if (selectedUserId) {
11244
11450
  // Find the selected user from the results for this specific family member
11245
11451
  const userResults = this.userSearchResults()[familyIndex] || [];
@@ -11258,26 +11464,124 @@ class CideCoreUserCreateComponent {
11258
11464
  designationOptions = signal({}, ...(ngDevMode ? [{ debugName: "designationOptions" }] : []));
11259
11465
  departmentOptions = signal({}, ...(ngDevMode ? [{ debugName: "departmentOptions" }] : []));
11260
11466
  menuOptions = signal([], ...(ngDevMode ? [{ debugName: "menuOptions" }] : []));
11261
- permissionOptions = signal([], ...(ngDevMode ? [{ debugName: "permissionOptions" }] : []));
11262
- entityRoleMap = signal({}, ...(ngDevMode ? [{ debugName: "entityRoleMap" }] : []));
11263
11467
  // Role permissions grid properties
11264
11468
  rolePermissionsGridConfig = signal({
11265
- id: 'role-permissions-grid',
11266
- columns: [],
11469
+ id: 'menu-list-grid',
11470
+ title: '',
11471
+ subtitle: '',
11472
+ columns: [
11473
+ {
11474
+ key: 'details',
11475
+ header: 'Menu Item',
11476
+ type: 'custom',
11477
+ width: 'auto',
11478
+ truncate: true,
11479
+ align: 'left',
11480
+ renderer: 'menuDetailsRenderer'
11481
+ },
11482
+ {
11483
+ key: 'syme_type',
11484
+ header: 'Type',
11485
+ type: 'custom',
11486
+ width: '120px',
11487
+ truncate: false,
11488
+ align: 'center',
11489
+ renderer: 'menuTypeRenderer'
11490
+ },
11491
+ {
11492
+ key: 'syme_path',
11493
+ header: 'Path',
11494
+ type: 'text',
11495
+ width: '200px',
11496
+ truncate: true,
11497
+ align: 'left'
11498
+ },
11499
+ {
11500
+ key: 'syme_isactive',
11501
+ header: 'Status',
11502
+ type: 'status',
11503
+ width: '100px',
11504
+ truncate: false,
11505
+ align: 'center',
11506
+ statusConfig: {
11507
+ activeValue: true,
11508
+ activeLabel: 'Active',
11509
+ inactiveLabel: 'Inactive',
11510
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
11511
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
11512
+ }
11513
+ },
11514
+ {
11515
+ key: 'syme_permissions_id_sygms',
11516
+ header: 'Permissions',
11517
+ type: 'custom',
11518
+ width: '200px',
11519
+ truncate: true,
11520
+ align: 'left',
11521
+ renderer: 'permissionsRenderer'
11522
+ },
11523
+ {
11524
+ key: 'actions',
11525
+ header: '',
11526
+ type: 'custom',
11527
+ width: '60px',
11528
+ truncate: false,
11529
+ align: 'center',
11530
+ renderer: 'actionsDropdownRenderer'
11531
+ }
11532
+ ],
11267
11533
  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: '' },
11534
+ trackBy: '_id',
11535
+ pagination: {
11536
+ enabled: false,
11537
+ pageSize: 10,
11538
+ pageSizeOptions: [10, 25, 50, 100],
11539
+ showQuickJump: true,
11540
+ showPageInfo: true,
11541
+ showRefresh: true
11542
+ },
11543
+ search: {
11544
+ enabled: true,
11545
+ placeholder: 'Search menu items...',
11546
+ searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
11547
+ debounceMs: 300
11548
+ },
11549
+ loading: {
11550
+ useDefer: true,
11551
+ skeletonRows: 5,
11552
+ showOverlay: false
11553
+ },
11554
+ scroll: {
11555
+ enabled: true,
11556
+ maxHeight: '',
11557
+ minHeight: '',
11558
+ stickyHeader: true,
11559
+ virtualScroll: false,
11560
+ rowHeight: 50
11561
+ },
11562
+ dragDrop: {
11563
+ enabled: true,
11564
+ orderField: 'syme_order_by',
11565
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
11566
+ dropClass: 'tw-bg-green-50'
11567
+ },
11273
11568
  responsive: true,
11274
11569
  striped: false,
11275
11570
  bordered: true,
11276
11571
  compact: false,
11277
- tableClass: '',
11278
- tree: { enabled: true, primaryKey: '_id', foreignKey: 'syme_parent_id_syme' }
11572
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
11573
+ onRefresh: 'onMenuItemRefresh',
11574
+ onRowReorder: 'onRowReorder',
11575
+ tree: {
11576
+ enabled: true,
11577
+ primaryKey: '_id',
11578
+ foreignKey: 'syme_id_syme',
11579
+ childrenKey: 'children',
11580
+ levelKey: 'level',
11581
+ expandedKey: 'isExpanded',
11582
+ hasChildrenKey: 'hasChildren'
11583
+ }
11279
11584
  }, ...(ngDevMode ? [{ debugName: "rolePermissionsGridConfig" }] : []));
11280
- selectedRolePermissions = signal([], ...(ngDevMode ? [{ debugName: "selectedRolePermissions" }] : []));
11281
11585
  selectedRoleId = signal(null, ...(ngDevMode ? [{ debugName: "selectedRoleId" }] : []));
11282
11586
  selectedEntityIndex = signal(null, ...(ngDevMode ? [{ debugName: "selectedEntityIndex" }] : []));
11283
11587
  // Template renderers for role permissions grid
@@ -11285,6 +11589,7 @@ class CideCoreUserCreateComponent {
11285
11589
  permissionsCheckboxRendererTemplate = viewChild('permissionsCheckboxRendererTemplate', ...(ngDevMode ? [{ debugName: "permissionsCheckboxRendererTemplate" }] : []));
11286
11590
  menuTypeRendererTemplate = viewChild('menuTypeRendererTemplate', ...(ngDevMode ? [{ debugName: "menuTypeRendererTemplate" }] : []));
11287
11591
  menuRightsPermissionsRendererTemplate = viewChild('menuRightsPermissionsRendererTemplate', ...(ngDevMode ? [{ debugName: "menuRightsPermissionsRendererTemplate" }] : []));
11592
+ permissionsRendererTemplate = viewChild('permissionsRendererTemplate', ...(ngDevMode ? [{ debugName: "permissionsRendererTemplate" }] : []));
11288
11593
  addressTypeOptions = signal([], ...(ngDevMode ? [{ debugName: "addressTypeOptions" }] : []));
11289
11594
  // Document and Family dropdown options
11290
11595
  documentTypeOptions = signal([], ...(ngDevMode ? [{ debugName: "documentTypeOptions" }] : []));
@@ -11327,12 +11632,24 @@ class CideCoreUserCreateComponent {
11327
11632
  }
11328
11633
  // Always load dropdown options
11329
11634
  this.loadDropdownOptions();
11635
+ this.loadUserRightsTypeId(); // Load user rights type and permissions
11330
11636
  this.setupFormSubscriptions();
11331
11637
  this.setEntityIdFromAppState();
11638
+ // Set up floating uploader with current user ID
11639
+ this.setupFloatingUploader();
11332
11640
  // Load initial users for family member selection
11333
11641
  this.loadInitialUsers();
11334
11642
  });
11335
11643
  }
11644
+ /**
11645
+ * Setup floating uploader with current user ID
11646
+ */
11647
+ setupFloatingUploader() {
11648
+ // Get current user ID from app state or use a default
11649
+ const currentUser = this.appState.getCurrentUser();
11650
+ const currentUserId = currentUser?._id || 'current-user';
11651
+ console.log('🚀 [UserCreate] Current user ID:', currentUserId);
11652
+ }
11336
11653
  /**
11337
11654
  * Setup form subscriptions
11338
11655
  */
@@ -11468,7 +11785,6 @@ class CideCoreUserCreateComponent {
11468
11785
  */
11469
11786
  loadUserData(userId) {
11470
11787
  this.loading.set(true);
11471
- this.error.set(null);
11472
11788
  // Create payload using the updated service pattern
11473
11789
  const getPayload = new AuthUserMstGetByIdPayload({
11474
11790
  user_id: userId,
@@ -11483,13 +11799,19 @@ class CideCoreUserCreateComponent {
11483
11799
  this.populateFormWithUserData(response.data);
11484
11800
  }
11485
11801
  else {
11486
- this.error.set(response.message || 'Failed to load user data');
11802
+ this.notificationService.error(response.message || 'Failed to load user data', {
11803
+ title: 'Load Failed',
11804
+ duration: 5000
11805
+ });
11487
11806
  }
11488
11807
  this.loading.set(false);
11489
11808
  },
11490
11809
  error: (error) => {
11491
11810
  console.error('Error loading user data:', error);
11492
- this.error.set('Failed to load user data. Please try again.');
11811
+ this.notificationService.error('Failed to load user data. Please try again.', {
11812
+ title: 'Load Failed',
11813
+ duration: 5000
11814
+ });
11493
11815
  this.loading.set(false);
11494
11816
  }
11495
11817
  });
@@ -11541,9 +11863,42 @@ class CideCoreUserCreateComponent {
11541
11863
  mappingGroup.get('syenm_entity_id_syen')?.disable();
11542
11864
  entityMappingFormArray.push(mappingGroup);
11543
11865
  });
11866
+ // Load role permissions for each mapping that has a role selected
11867
+ data.core_entity_mapping.forEach((mapping, index) => {
11868
+ if (mapping.syenm_role_id_syusrol) {
11869
+ const roleId = typeof mapping.syenm_role_id_syusrol === 'object'
11870
+ ? mapping.syenm_role_id_syusrol._id
11871
+ : mapping.syenm_role_id_syusrol;
11872
+ if (roleId) {
11873
+ console.log(`🎭 Loading role permissions for mapping ${index} with role ${roleId}`);
11874
+ this.loadRolePermissions(roleId, index);
11875
+ }
11876
+ }
11877
+ });
11544
11878
  }
11545
- if (data.menu_rights) {
11546
- this.menuRightsMap.set(data.menu_rights);
11879
+ // Handle existing role exceptions
11880
+ if (data.core_user_role_exceptions && Array.isArray(data.core_user_role_exceptions)) {
11881
+ console.log('🎭 Loading existing role exceptions:', data.core_user_role_exceptions);
11882
+ // Group exceptions by mapping index
11883
+ const exceptionsByMapping = {};
11884
+ data.core_user_role_exceptions.forEach((exception) => {
11885
+ // Find the mapping index for this exception
11886
+ const mappingIndex = this.findMappingIndexByEntityMappingId(exception.syusrex_user_entity_mapping_id_syenm || '');
11887
+ if (mappingIndex !== null) {
11888
+ if (!exceptionsByMapping[mappingIndex.toString()]) {
11889
+ exceptionsByMapping[mappingIndex.toString()] = [];
11890
+ }
11891
+ exceptionsByMapping[mappingIndex.toString()].push(exception);
11892
+ }
11893
+ });
11894
+ // Add exceptions to each mapping
11895
+ Object.keys(exceptionsByMapping).forEach(mappingIndexStr => {
11896
+ const mappingIndex = parseInt(mappingIndexStr);
11897
+ const mapping = this.entityMappings()[mappingIndex];
11898
+ if (mapping) {
11899
+ mapping.exceptions = exceptionsByMapping[mappingIndexStr];
11900
+ }
11901
+ });
11547
11902
  }
11548
11903
  if (data.core_user_contact_addresses) {
11549
11904
  this.contactAddresses.set(data.core_user_contact_addresses);
@@ -11578,6 +11933,7 @@ class CideCoreUserCreateComponent {
11578
11933
  const documentGroup = this.createDocumentFormGroup();
11579
11934
  documentGroup.patchValue({
11580
11935
  _id: document._id || '',
11936
+ syusd_user_id_user: this.appState.getUserId() || '',
11581
11937
  syusd_document_type_id_sygms: document.syusd_document_type_id_sygms?._id || '',
11582
11938
  syusd_doc_number: document.syusd_doc_number || '',
11583
11939
  syusd_doc_name_as_per_doc: document.syusd_doc_name_as_per_doc || '',
@@ -11585,9 +11941,7 @@ class CideCoreUserCreateComponent {
11585
11941
  syusd_doc_issue_date: document.syusd_doc_issue_date || '',
11586
11942
  syusd_doc_expiry_date: document.syusd_doc_expiry_date || '',
11587
11943
  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 || '',
11944
+ syusd_doc_kyc_status_id_sygms: document.syusd_doc_kyc_status_id_sygms?._id || '',
11591
11945
  syusd_isactive: document.syusd_isactive ?? true
11592
11946
  });
11593
11947
  this.documentsFormArray.push(documentGroup);
@@ -11643,25 +11997,8 @@ class CideCoreUserCreateComponent {
11643
11997
  this.loadDocumentKycStatus();
11644
11998
  this.loadBloodGroups();
11645
11999
  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
- ]);
12000
+ // Load menu options from API
12001
+ this.loadMenuOptions();
11665
12002
  }
11666
12003
  relationshipOptions() {
11667
12004
  return this.relationshipOptionsData();
@@ -11727,6 +12064,12 @@ class CideCoreUserCreateComponent {
11727
12064
  }
11728
12065
  // Trigger change detection to update other entity dropdowns
11729
12066
  this.triggerEntityDropdownUpdate();
12067
+ // Automatically load menu rights when both entity and role are selected
12068
+ const mapping = this.entityMappings()[mappingIndex];
12069
+ if (mapping?.syenm_entity_id_syen && mapping?.syenm_role_id_syusrol) {
12070
+ console.log(`🚀 Auto-loading menu rights for mapping ${mappingIndex}`);
12071
+ this.loadMenuRights(mappingIndex);
12072
+ }
11730
12073
  // For now, we'll use all available roles
11731
12074
  // In a real implementation, you'd filter roles based on the entity
11732
12075
  }
@@ -11981,10 +12324,9 @@ class CideCoreUserCreateComponent {
11981
12324
  */
11982
12325
  initializeRolePermissionsGrid() {
11983
12326
  this.rolePermissionsGridConfig.set({
11984
- id: 'role-permissions-grid',
11985
- title: 'Role Permissions',
11986
- subtitle: 'Select permissions for the chosen role',
11987
- fullHeight: true,
12327
+ id: 'menu-list-grid',
12328
+ title: '',
12329
+ subtitle: '',
11988
12330
  columns: [
11989
12331
  {
11990
12332
  key: 'details',
@@ -12004,14 +12346,46 @@ class CideCoreUserCreateComponent {
12004
12346
  align: 'center',
12005
12347
  renderer: 'menuTypeRenderer'
12006
12348
  },
12349
+ {
12350
+ key: 'syme_path',
12351
+ header: 'Path',
12352
+ type: 'text',
12353
+ width: '200px',
12354
+ truncate: true,
12355
+ align: 'left'
12356
+ },
12357
+ {
12358
+ key: 'syme_isactive',
12359
+ header: 'Status',
12360
+ type: 'status',
12361
+ width: '100px',
12362
+ truncate: false,
12363
+ align: 'center',
12364
+ statusConfig: {
12365
+ activeValue: true,
12366
+ activeLabel: 'Active',
12367
+ inactiveLabel: 'Inactive',
12368
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
12369
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
12370
+ }
12371
+ },
12007
12372
  {
12008
12373
  key: 'syme_permissions_id_sygms',
12009
- header: 'Available Permissions',
12374
+ header: 'Permissions',
12010
12375
  type: 'custom',
12011
- width: '300px',
12012
- truncate: false,
12376
+ width: '200px',
12377
+ truncate: true,
12013
12378
  align: 'left',
12014
- renderer: 'permissionsCheckboxRenderer'
12379
+ renderer: 'permissionsRenderer'
12380
+ },
12381
+ {
12382
+ key: 'actions',
12383
+ header: '',
12384
+ type: 'custom',
12385
+ width: '60px',
12386
+ truncate: false,
12387
+ align: 'center',
12388
+ renderer: 'actionsDropdownRenderer'
12015
12389
  }
12016
12390
  ],
12017
12391
  data: [],
@@ -12031,20 +12405,20 @@ class CideCoreUserCreateComponent {
12031
12405
  debounceMs: 300
12032
12406
  },
12033
12407
  loading: {
12034
- useDefer: false,
12408
+ useDefer: true,
12035
12409
  skeletonRows: 5,
12036
12410
  showOverlay: false
12037
12411
  },
12038
12412
  scroll: {
12039
12413
  enabled: true,
12040
- maxHeight: '400px',
12041
- minHeight: '200px',
12414
+ maxHeight: '',
12415
+ minHeight: '',
12042
12416
  stickyHeader: true,
12043
12417
  virtualScroll: false,
12044
- rowHeight: 25
12418
+ rowHeight: 50
12045
12419
  },
12046
12420
  dragDrop: {
12047
- enabled: false,
12421
+ enabled: true,
12048
12422
  orderField: 'syme_order_by',
12049
12423
  dragClass: 'tw-opacity-50 tw-bg-blue-50',
12050
12424
  dropClass: 'tw-bg-green-50'
@@ -12054,10 +12428,16 @@ class CideCoreUserCreateComponent {
12054
12428
  bordered: true,
12055
12429
  compact: false,
12056
12430
  tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
12431
+ onRefresh: 'onMenuItemRefresh',
12432
+ onRowReorder: 'onRowReorder',
12057
12433
  tree: {
12058
12434
  enabled: true,
12059
12435
  primaryKey: '_id',
12060
- foreignKey: 'syme_parent_id_syme'
12436
+ foreignKey: 'syme_id_syme',
12437
+ childrenKey: 'children',
12438
+ levelKey: 'level',
12439
+ expandedKey: 'isExpanded',
12440
+ hasChildrenKey: 'hasChildren'
12061
12441
  }
12062
12442
  });
12063
12443
  }
@@ -12073,12 +12453,22 @@ class CideCoreUserCreateComponent {
12073
12453
  this.selectedEntityIndex.set(mappingIndex);
12074
12454
  this.selectedRoleId.set(roleId);
12075
12455
  // Load role details and permissions
12076
- this.loadRolePermissions(roleId);
12456
+ this.loadRolePermissions(roleId, mappingIndex);
12457
+ // Automatically load menu rights when both entity and role are selected
12458
+ const mapping = this.entityMappings()[mappingIndex];
12459
+ if (mapping?.syenm_entity_id_syen && mapping?.syenm_role_id_syusrol) {
12460
+ console.log(`🚀 Auto-loading menu rights for mapping ${mappingIndex}`);
12461
+ this.loadMenuRights(mappingIndex);
12462
+ // Force refresh the grid to show updated permission states
12463
+ setTimeout(() => {
12464
+ this.cdr.detectChanges();
12465
+ }, 100);
12466
+ }
12077
12467
  }
12078
12468
  /**
12079
12469
  * Load role permissions from API
12080
12470
  */
12081
- loadRolePermissions(roleId) {
12471
+ loadRolePermissions(roleId, mappingIndex) {
12082
12472
  console.log(`🎭 Loading permissions for role:`, roleId);
12083
12473
  this.loading.set(true);
12084
12474
  // Load role details by ID
@@ -12086,136 +12476,132 @@ class CideCoreUserCreateComponent {
12086
12476
  next: (response) => {
12087
12477
  if (response?.success && response.data) {
12088
12478
  console.log(`🎭 Role details loaded:`, response.data);
12089
- // Load menus and permissions for the role
12090
- this.loadMenusAndPermissionsForRole(response.data);
12479
+ // Store role permissions for simple lookup
12480
+ this.storeRolePermissions(response.data, mappingIndex);
12091
12481
  }
12092
12482
  else {
12093
12483
  console.error(`❌ Failed to load role details:`, response);
12094
- this.error.set('Failed to load role permissions');
12484
+ this.notificationService.error('Failed to load role permissions', {
12485
+ title: 'Load Failed',
12486
+ duration: 5000
12487
+ });
12095
12488
  }
12096
12489
  this.loading.set(false);
12097
12490
  },
12098
12491
  error: (error) => {
12099
12492
  console.error(`❌ Error loading role details:`, error);
12100
- this.error.set('Error loading role permissions');
12493
+ this.notificationService.error('Error loading role permissions', {
12494
+ title: 'Load Failed',
12495
+ duration: 5000
12496
+ });
12101
12497
  this.loading.set(false);
12102
12498
  }
12103
12499
  });
12104
12500
  }
12105
12501
  /**
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
12502
+ * Update permission values for a specific menu row
12121
12503
  */
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');
12504
+ updateMenuPermissionValues(mappingIndex, menuId) {
12505
+ this.menuRightsMap.update(map => {
12506
+ const newMap = { ...map };
12507
+ const menuRights = newMap[mappingIndex.toString()] || [];
12508
+ const updatedMenuRights = menuRights.map(menu => {
12509
+ if (menu._id === menuId) {
12510
+ // Re-compute permission values for this menu
12511
+ const permissionValues = {};
12512
+ if (menu.syme_permissions_id_sygms) {
12513
+ menu.syme_permissions_id_sygms.forEach(permissionId => {
12514
+ const permission = this.getPermissionById(permissionId);
12515
+ if (permission) {
12516
+ permissionValues[permissionId] = {
12517
+ checked: this.getFormControlValue(menu, permissionId),
12518
+ permission: permission
12519
+ };
12520
+ }
12521
+ });
12143
12522
  }
12144
- },
12145
- error: (error) => {
12146
- console.error(`❌ Error loading menus:`, error);
12147
- reject(error);
12523
+ return {
12524
+ ...menu,
12525
+ _permissionValues: permissionValues
12526
+ };
12148
12527
  }
12528
+ return menu;
12149
12529
  });
12530
+ newMap[mappingIndex.toString()] = updatedMenuRights;
12531
+ return newMap;
12150
12532
  });
12151
12533
  }
12152
12534
  /**
12153
- * Load permissions from API
12535
+ * Store role permissions for simple lookup
12154
12536
  */
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');
12537
+ storeRolePermissions(roleData, mappingIndex) {
12538
+ console.log(`🎭 Storing role permissions for mapping ${mappingIndex}:`, roleData);
12539
+ // Extract role permissions from the role data
12540
+ const roleRights = roleData.core_user_role_rights;
12541
+ if (roleRights && Array.isArray(roleRights)) {
12542
+ // Store role permissions as objects with ID and title
12543
+ const rolePermissionObjects = roleRights.map((right) => {
12544
+ const permission = right.syusrgt_role_permissions_id_sygms;
12545
+ return {
12546
+ _id: permission?._id,
12547
+ sygms_title: permission?.sygms_title,
12548
+ menu_id: right.syusrgt_menu_id_syme?._id
12549
+ };
12550
+ }).filter((permission) => permission._id && permission.sygms_title);
12551
+ // Update menuRightsMap with role permissions for each menu
12552
+ this.menuRightsMap.update(menuMap => {
12553
+ const newMenuMap = { ...menuMap };
12554
+ const currentMenuRights = newMenuMap[mappingIndex.toString()] || [];
12555
+ // Update each menu with its role permissions
12556
+ const updatedMenuRights = currentMenuRights.map(menu => {
12557
+ if (menu._id) {
12558
+ const menuSpecificPermissions = rolePermissionObjects
12559
+ .filter(permission =>
12560
+ // Permission must be in the menu's allowed permissions list
12561
+ menu.syme_permissions_id_sygms?.includes(permission._id) &&
12562
+ // AND must be assigned to this menu in the role data
12563
+ permission.menu_id === menu._id);
12564
+ return {
12565
+ ...menu,
12566
+ _rolePermissions: menuSpecificPermissions
12567
+ };
12168
12568
  }
12169
- },
12170
- error: (error) => {
12171
- console.error(`❌ Error loading permissions:`, error);
12172
- reject(error);
12173
- }
12569
+ return menu;
12570
+ });
12571
+ newMenuMap[mappingIndex.toString()] = updatedMenuRights;
12572
+ return newMenuMap;
12174
12573
  });
12175
- });
12176
- }
12177
- /**
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);
12574
+ // Update permission values for all menus in this mapping
12575
+ const menuRights = this.menuRightsMap()[mappingIndex.toString()] || [];
12576
+ menuRights.forEach(menu => {
12577
+ if (menu._id) {
12578
+ this.updateMenuPermissionValues(mappingIndex, menu._id);
12579
+ }
12190
12580
  });
12581
+ console.log(`🎭 Stored role permission objects for mapping ${mappingIndex}:`, rolePermissionObjects);
12582
+ }
12583
+ else {
12584
+ console.log(`🎭 No role permissions found in role data`);
12191
12585
  }
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
12586
  }
12208
12587
  /**
12209
12588
  * Clear role permissions
12210
12589
  */
12211
12590
  clearRolePermissions() {
12212
- this.selectedRolePermissions.set([]);
12213
12591
  this.selectedRoleId.set(null);
12214
12592
  this.selectedEntityIndex.set(null);
12215
- this.rolePermissionsGridConfig.update(config => ({
12216
- ...config,
12217
- data: []
12218
- }));
12593
+ }
12594
+ /**
12595
+ * Find mapping index by entity mapping ID
12596
+ */
12597
+ findMappingIndexByEntityMappingId(entityMappingId) {
12598
+ const mappings = this.entityMappings();
12599
+ for (let i = 0; i < mappings.length; i++) {
12600
+ if (mappings[i]._id === entityMappingId) {
12601
+ return i;
12602
+ }
12603
+ }
12604
+ return null;
12219
12605
  }
12220
12606
  /**
12221
12607
  * Handle grid events for role permissions
@@ -12247,20 +12633,272 @@ class CideCoreUserCreateComponent {
12247
12633
  * Get permission by ID
12248
12634
  */
12249
12635
  getPermissionById(permissionId) {
12250
- return this.permissionOptions().find(permission => permission._id === permissionId);
12636
+ return this.permissions().find(permission => permission._id === permissionId);
12251
12637
  }
12252
12638
  /**
12253
- * Check if permission is selected for a menu
12639
+ * Check if permission is available in the selected role for a specific menu
12254
12640
  */
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;
12641
+ isPermissionInRole(permissionId, mappingIndex, menuId) {
12642
+ const mapping = this.entityMappings()[mappingIndex];
12643
+ const roleId = mapping?.syenm_role_id_syusrol;
12644
+ console.log(`🎭 Checking permission ${permissionId} for role:`, roleId, 'menu:', menuId);
12645
+ if (!roleId || !menuId) {
12646
+ console.log(`🎭 No role ID or menu ID found for mapping ${mappingIndex}`);
12647
+ return false;
12648
+ }
12649
+ // Get role permissions from the menu objects in menuRightsMap
12650
+ const menuRights = this.menuRightsMap()[mappingIndex.toString()] || [];
12651
+ const menu = menuRights.find(m => m._id === menuId);
12652
+ if (menu && menu._rolePermissions) {
12653
+ const rolePermissions = menu._rolePermissions;
12654
+ const isInRole = rolePermissions.some((permission) => permission._id === permissionId && permission.menu_id === menuId);
12655
+ console.log(`🎭 Permission ${permissionId} in role for menu ${menuId}: ${isInRole}`);
12656
+ return isInRole;
12261
12657
  }
12658
+ console.log(`🎭 No role permissions found for mapping ${mappingIndex}, menu ${menuId}`);
12262
12659
  return false;
12263
12660
  }
12661
+ /**
12662
+ * Get form control value for a permission
12663
+ */
12664
+ getFormControlValue(row, permissionId) {
12665
+ console.log(`🎭 Getting form control value for permission: ${permissionId} for menu: ${row.syme_title}`, row);
12666
+ const permission = this.getPermissionById(permissionId);
12667
+ if (!permission) {
12668
+ console.log(`🎭 Permission not found for ID: ${permissionId}`);
12669
+ return false;
12670
+ }
12671
+ // Find the current mapping index
12672
+ const mappingIndex = this.getCurrentMappingIndex();
12673
+ if (mappingIndex === null) {
12674
+ console.log(`🎭 No current mapping index found`);
12675
+ return false;
12676
+ }
12677
+ // Check if permission is available in the role for this specific menu
12678
+ const isRolePermission = this.isPermissionInRole(permissionId, mappingIndex, row._id);
12679
+ console.log(`🎭 Permission ${permission.sygms_title} for menu ${row.syme_title}: isRolePermission = ${isRolePermission}`);
12680
+ if (isRolePermission) {
12681
+ // If permission is in role, it should be checked by default
12682
+ console.log(`🎭 Returning true for role permission: ${permission.sygms_title}`);
12683
+ return true;
12684
+ }
12685
+ else {
12686
+ // If permission is not in role, check if it's added as exception
12687
+ const mapping = this.entityMappings()[mappingIndex];
12688
+ const exceptions = mapping.exceptions || [];
12689
+ const isException = exceptions.some((exception) => exception.syusrex_menu_id_syme === row._id &&
12690
+ exception.syusrex_role_permissions_id_sygms === permissionId);
12691
+ console.log(`🎭 Permission ${permission.sygms_title} is exception: ${isException}`);
12692
+ return isException;
12693
+ }
12694
+ }
12695
+ /**
12696
+ * Handle permission change with type safety
12697
+ */
12698
+ onPermissionChangeSafe(checked, row, permissionId) {
12699
+ this.onPermissionChange(Boolean(checked), row, permissionId);
12700
+ }
12701
+ /**
12702
+ * Handle permission change
12703
+ */
12704
+ onPermissionChange(checked, row, permissionId) {
12705
+ const permission = this.getPermissionById(permissionId);
12706
+ if (!permission)
12707
+ return;
12708
+ // Find the current mapping index
12709
+ const mappingIndex = this.getCurrentMappingIndex();
12710
+ if (mappingIndex === null)
12711
+ return;
12712
+ // Check if permission is in role for this specific menu
12713
+ const isRolePermission = this.isPermissionInRole(permissionId, mappingIndex, row._id);
12714
+ if (isRolePermission) {
12715
+ // Role permissions are handled by the role itself, no form controls needed
12716
+ console.log('🎭 Role permission (handled by role):', {
12717
+ menu: row.syme_title,
12718
+ permission: permission.sygms_title,
12719
+ checked: checked
12720
+ });
12721
+ }
12722
+ else {
12723
+ // Handle exception permission
12724
+ if (checked) {
12725
+ // Add exception
12726
+ this.addRoleException(mappingIndex, row._id || '', permissionId);
12727
+ }
12728
+ else {
12729
+ // Remove exception
12730
+ this.removeRoleException(mappingIndex, row._id || '', permissionId);
12731
+ }
12732
+ console.log('🎭 Exception permission changed:', {
12733
+ menu: row.syme_title,
12734
+ permission: permission.sygms_title,
12735
+ checked: checked
12736
+ });
12737
+ }
12738
+ // Update the pre-computed permission values for this menu
12739
+ this.updateMenuPermissionValues(mappingIndex, row._id || '');
12740
+ }
12741
+ /**
12742
+ * Handle permission change for specific mapping
12743
+ */
12744
+ onPermissionChangeForMapping(checked, row, permissionId, mappingIndex) {
12745
+ const permission = this.getPermissionById(permissionId);
12746
+ if (!permission)
12747
+ return;
12748
+ const controlName = `core_entity_mapping.${mappingIndex}.menu_rights.${row._id}.${permission.sygms_title}`;
12749
+ this.userMasterForm.get(controlName)?.setValue(checked);
12750
+ console.log('🎭 Permission changed for mapping:', {
12751
+ mappingIndex,
12752
+ menu: row.syme_title,
12753
+ permission: permission.sygms_title,
12754
+ checked: checked,
12755
+ controlName
12756
+ });
12757
+ }
12758
+ /**
12759
+ * Get current mapping index (helper method)
12760
+ */
12761
+ getCurrentMappingIndex() {
12762
+ // Find the mapping index that has both entity and role selected
12763
+ const entityMappings = this.entityMappings();
12764
+ for (let i = 0; i < entityMappings.length; i++) {
12765
+ const entityId = this.userMasterForm.get(`core_entity_mapping.${i}.syenm_entity_id_syen`)?.value;
12766
+ const roleId = this.userMasterForm.get(`core_entity_mapping.${i}.syenm_role_id_syusrol`)?.value;
12767
+ if (entityId && roleId) {
12768
+ return i;
12769
+ }
12770
+ }
12771
+ return null;
12772
+ }
12773
+ /**
12774
+ * Add role exception
12775
+ */
12776
+ addRoleException(mappingIndex, menuId, permissionId) {
12777
+ const mapping = this.entityMappings()[mappingIndex];
12778
+ const permission = this.getPermissionById(permissionId);
12779
+ if (!mapping || !permission)
12780
+ return;
12781
+ // Get the role ID directly (not as object)
12782
+ const roleId = typeof mapping.syenm_role_id_syusrol === 'object'
12783
+ ? mapping.syenm_role_id_syusrol?._id ?? ''
12784
+ : mapping.syenm_role_id_syusrol ?? '';
12785
+ // Create exception object with change tracking
12786
+ const exception = {
12787
+ syusrex_user_entity_mapping_id_syenm: mapping._id || '',
12788
+ syusrex_role_id_syusrol: roleId, // Direct ID string
12789
+ syusrex_role_permissions_id_sygms: permissionId,
12790
+ syusrex_menu_id_syme: menuId,
12791
+ syusrex_isactive: true,
12792
+ _isUserAdded: true, // Mark as explicitly added by user
12793
+ _changeType: 'added' // Track the change type
12794
+ };
12795
+ // Add to entity mapping exceptions (check for duplicates first)
12796
+ this.entityMappings.update(mappings => {
12797
+ const updatedMappings = [...mappings];
12798
+ const mappingWithExceptions = updatedMappings[mappingIndex];
12799
+ if (!mappingWithExceptions.exceptions) {
12800
+ mappingWithExceptions.exceptions = [];
12801
+ }
12802
+ // Check if exception already exists to prevent duplicates
12803
+ const existingException = mappingWithExceptions.exceptions.find(ex => ex.syusrex_menu_id_syme === menuId &&
12804
+ ex.syusrex_role_permissions_id_sygms === permissionId);
12805
+ if (!existingException) {
12806
+ mappingWithExceptions.exceptions.push(exception);
12807
+ console.log('🎭 Role exception added (new):', exception);
12808
+ }
12809
+ else {
12810
+ // If exception exists but was removed, mark it as added again
12811
+ if (existingException._isUserRemoved) {
12812
+ existingException._isUserRemoved = false;
12813
+ existingException._isUserAdded = true;
12814
+ existingException._changeType = 'added';
12815
+ existingException.syusrex_isactive = true;
12816
+ console.log('🎭 Role exception reactivated:', existingException);
12817
+ }
12818
+ else {
12819
+ console.log('🎭 Role exception already exists, skipping duplicate:', existingException);
12820
+ }
12821
+ }
12822
+ return updatedMappings;
12823
+ });
12824
+ console.log('🎭 Role exception added:', exception);
12825
+ }
12826
+ /**
12827
+ * Remove role exception
12828
+ */
12829
+ removeRoleException(mappingIndex, menuId, permissionId) {
12830
+ this.entityMappings.update(mappings => {
12831
+ const updatedMappings = [...mappings];
12832
+ const mapping = updatedMappings[mappingIndex];
12833
+ if (mapping.exceptions) {
12834
+ // Instead of removing, mark as removed for tracking
12835
+ mapping.exceptions = mapping.exceptions.map((exception) => {
12836
+ if (exception.syusrex_menu_id_syme === menuId && exception.syusrex_role_permissions_id_sygms === permissionId) {
12837
+ return {
12838
+ ...exception,
12839
+ _isUserRemoved: true,
12840
+ _changeType: 'removed',
12841
+ syusrex_isactive: false
12842
+ };
12843
+ }
12844
+ return exception;
12845
+ });
12846
+ }
12847
+ return updatedMappings;
12848
+ });
12849
+ console.log('🎭 Role exception marked as removed:', { mappingIndex, menuId, permissionId });
12850
+ }
12851
+ /**
12852
+ * Collect only changed role exceptions from entity mappings
12853
+ */
12854
+ collectRoleExceptions() {
12855
+ const exceptions = [];
12856
+ const entityMappings = this.entityMappings();
12857
+ entityMappings.forEach((mapping, mappingIndex) => {
12858
+ // Get exceptions from the mapping
12859
+ const mappingWithExceptions = mapping;
12860
+ const mappingExceptions = mappingWithExceptions.exceptions || [];
12861
+ // Only include exceptions that have been explicitly changed by the user
12862
+ mappingExceptions.forEach((exception) => {
12863
+ // Check if this exception was explicitly added or removed by the user
12864
+ if (exception._isUserAdded || exception._isUserRemoved) {
12865
+ // Ensure role ID is direct string, not object
12866
+ const roleId = mapping.syenm_role_id_syusrol?._id ?? '';
12867
+ // Create a unique key for this exception to prevent duplicates
12868
+ const exceptionKey = `${mapping._id || `temp_${mappingIndex}`}_${roleId}_${exception.syusrex_role_permissions_id_sygms}_${exception.syusrex_menu_id_syme}`;
12869
+ // Check if this exception already exists in the collection
12870
+ const existingException = exceptions.find(ex => ex.syusrex_user_entity_mapping_id_syenm === (mapping._id || `temp_${mappingIndex}`) &&
12871
+ ex.syusrex_role_id_syusrol === roleId &&
12872
+ ex.syusrex_role_permissions_id_sygms === exception.syusrex_role_permissions_id_sygms &&
12873
+ ex.syusrex_menu_id_syme === exception.syusrex_menu_id_syme);
12874
+ if (!existingException) {
12875
+ exceptions.push({
12876
+ syusrex_user_entity_mapping_id_syenm: mapping._id || `temp_${mappingIndex}`,
12877
+ syusrex_role_id_syusrol: roleId,
12878
+ syusrex_role_permissions_id_sygms: exception.syusrex_role_permissions_id_sygms || '',
12879
+ syusrex_menu_id_syme: exception.syusrex_menu_id_syme || '',
12880
+ syusrex_isactive: exception.syusrex_isactive || false,
12881
+ _changeType: exception._changeType || 'unknown'
12882
+ });
12883
+ }
12884
+ else {
12885
+ console.log('🎭 Duplicate exception prevented:', exceptionKey);
12886
+ }
12887
+ }
12888
+ });
12889
+ });
12890
+ console.log('🎭 Collected changed role exceptions:', exceptions);
12891
+ return exceptions;
12892
+ }
12893
+ /**
12894
+ * Check if permission is selected for a menu
12895
+ */
12896
+ isPermissionSelected(menuId, permissionId) {
12897
+ const mappingIndex = this.getCurrentMappingIndex();
12898
+ if (mappingIndex === null)
12899
+ return false;
12900
+ return this.isPermissionInRole(permissionId, mappingIndex, menuId);
12901
+ }
12264
12902
  /**
12265
12903
  * Handle permission checkbox change (read-only in this context)
12266
12904
  */
@@ -12272,14 +12910,21 @@ class CideCoreUserCreateComponent {
12272
12910
  * Check if a menu has child menus with permissions
12273
12911
  */
12274
12912
  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);
12913
+ // For simplified approach, we don't need to check child menus
12914
+ // Just return false as we're not using hierarchical permission checking
12915
+ return false;
12916
+ }
12917
+ /**
12918
+ * Update menu rights grid data to force refresh
12919
+ */
12920
+ updateMenuRightsGridData(mappingIndex) {
12921
+ const menuRights = this.getMenuRightsForMapping(mappingIndex);
12922
+ console.log('🔄 Updating menu rights grid data:', menuRights);
12923
+ // Force update the grid configuration
12924
+ this.menuRightsMap.update(map => {
12925
+ const newMap = { ...map };
12926
+ newMap[mappingIndex.toString()] = menuRights;
12927
+ return newMap;
12283
12928
  });
12284
12929
  }
12285
12930
  /**
@@ -12287,11 +12932,13 @@ class CideCoreUserCreateComponent {
12287
12932
  */
12288
12933
  getMenuRightsGridConfig(mappingIndex) {
12289
12934
  const menuRights = this.getMenuRightsForMapping(mappingIndex);
12935
+ console.log(`🔍 Grid config for mapping ${mappingIndex}:`);
12936
+ console.log(`📊 Menu rights count:`, menuRights.length);
12937
+ console.log(`📋 Menu rights data:`, menuRights);
12290
12938
  return {
12291
12939
  id: `menu-rights-grid-${mappingIndex}`,
12292
- title: 'Menu Rights & Permissions',
12293
- subtitle: 'Manage permissions for this entity-role mapping',
12294
- fullHeight: true,
12940
+ title: '',
12941
+ subtitle: '',
12295
12942
  columns: [
12296
12943
  {
12297
12944
  key: 'details',
@@ -12312,17 +12959,40 @@ class CideCoreUserCreateComponent {
12312
12959
  renderer: 'menuTypeRenderer'
12313
12960
  },
12314
12961
  {
12315
- key: 'permissions',
12962
+ key: 'syme_path',
12963
+ header: 'Path',
12964
+ type: 'text',
12965
+ width: '200px',
12966
+ truncate: true,
12967
+ align: 'left'
12968
+ },
12969
+ {
12970
+ key: 'syme_isactive',
12971
+ header: 'Status',
12972
+ type: 'status',
12973
+ width: '100px',
12974
+ truncate: false,
12975
+ align: 'center',
12976
+ statusConfig: {
12977
+ activeValue: true,
12978
+ activeLabel: 'Active',
12979
+ inactiveLabel: 'Inactive',
12980
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
12981
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
12982
+ }
12983
+ },
12984
+ {
12985
+ key: 'syme_permissions_id_sygms',
12316
12986
  header: 'Permissions',
12317
12987
  type: 'custom',
12318
- width: '300px',
12319
- truncate: false,
12988
+ width: '200px',
12989
+ truncate: true,
12320
12990
  align: 'left',
12321
12991
  renderer: 'permissionsRenderer'
12322
12992
  }
12323
12993
  ],
12324
12994
  data: menuRights,
12325
- trackBy: 'menu_id',
12995
+ trackBy: '_id',
12326
12996
  pagination: {
12327
12997
  enabled: false,
12328
12998
  pageSize: 10,
@@ -12334,37 +13004,43 @@ class CideCoreUserCreateComponent {
12334
13004
  search: {
12335
13005
  enabled: true,
12336
13006
  placeholder: 'Search menu items...',
12337
- searchableColumns: ['menu_name', 'menu_code'],
13007
+ searchableColumns: ['syme_title', 'syme_desc', 'syme_path'],
12338
13008
  debounceMs: 300
12339
13009
  },
12340
13010
  loading: {
12341
- useDefer: false,
13011
+ useDefer: true,
12342
13012
  skeletonRows: 5,
12343
13013
  showOverlay: false
12344
13014
  },
12345
13015
  scroll: {
12346
13016
  enabled: true,
12347
- maxHeight: '400px',
12348
- minHeight: '200px',
13017
+ maxHeight: '',
13018
+ minHeight: '',
12349
13019
  stickyHeader: true,
12350
13020
  virtualScroll: false,
12351
- rowHeight: 25
13021
+ rowHeight: 50
12352
13022
  },
12353
13023
  dragDrop: {
12354
- enabled: false,
12355
- orderField: '',
12356
- dragClass: '',
12357
- dropClass: ''
13024
+ enabled: true,
13025
+ orderField: 'syme_order_by',
13026
+ dragClass: 'tw-opacity-50 tw-bg-blue-50',
13027
+ dropClass: 'tw-bg-green-50'
12358
13028
  },
12359
13029
  responsive: true,
12360
13030
  striped: false,
12361
13031
  bordered: true,
12362
13032
  compact: false,
12363
13033
  tableClass: 'tw-table-fixed tw-w-full tw-rounded-none',
13034
+ onRefresh: 'onMenuItemRefresh',
13035
+ onRowReorder: 'onRowReorder',
12364
13036
  tree: {
12365
13037
  enabled: true,
12366
- primaryKey: 'menu_id',
12367
- foreignKey: 'parent_menu_id'
13038
+ primaryKey: '_id',
13039
+ foreignKey: 'syme_id_syme',
13040
+ childrenKey: 'children',
13041
+ levelKey: 'level',
13042
+ expandedKey: 'isExpanded',
13043
+ hasChildrenKey: 'hasChildren'
12368
13044
  }
12369
13045
  };
12370
13046
  }
@@ -12375,7 +13051,7 @@ class CideCoreUserCreateComponent {
12375
13051
  return {
12376
13052
  menuDetailsRenderer: this.menuDetailsRendererTemplate(),
12377
13053
  menuTypeRenderer: this.menuTypeRendererTemplate(),
12378
- permissionsRenderer: this.menuRightsPermissionsRendererTemplate()
13054
+ permissionsRenderer: this.permissionsRendererTemplate()
12379
13055
  };
12380
13056
  }
12381
13057
  /**
@@ -12448,71 +13124,104 @@ class CideCoreUserCreateComponent {
12448
13124
  console.warn('Entity and Role must be selected before loading menu rights');
12449
13125
  return;
12450
13126
  }
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: []
13127
+ console.log('🚀 Loading menu rights for mapping:', mappingIndex);
13128
+ this.loading.set(true);
13129
+ // Use actual API call to get menu list
13130
+ const requestBody = {
13131
+ pageIndex: 1,
13132
+ pageSize: 1000, // Get all menu items - increased to ensure we get all records
13133
+ total: 1000, // Set total to match pageSize to get all records
13134
+ sort: { order: 'asc', key: 'syme_order_by' }
13135
+ };
13136
+ console.log('📤 Request body for menu list:', requestBody);
13137
+ this.menuService.getMenuList(requestBody)
13138
+ .pipe(takeUntilDestroyed(this.destroyRef))
13139
+ .subscribe({
13140
+ next: (response) => {
13141
+ console.log('✅ Menu list loaded successfully:', response);
13142
+ console.log('📊 Total menu items received:', response?.data?.length || 0);
13143
+ console.log('📋 Menu items data:', response?.data);
13144
+ if (response?.success && response?.data) {
13145
+ // Use menu data directly without transformation
13146
+ const menuRights = response.data.map((menu) => {
13147
+ // Get only the permissions that are mapped to this menu
13148
+ const mappedPermissions = this.permissions().filter(permission => menu.syme_permissions_id_sygms?.includes(permission._id || ''));
13149
+ // Pre-compute permission values for template performance
13150
+ const permissionValues = {};
13151
+ if (menu.syme_permissions_id_sygms) {
13152
+ menu.syme_permissions_id_sygms.forEach(permissionId => {
13153
+ const permission = this.getPermissionById(permissionId);
13154
+ if (permission) {
13155
+ permissionValues[permissionId] = {
13156
+ checked: this.getFormControlValue(menu, permissionId),
13157
+ permission: permission
13158
+ };
13159
+ }
13160
+ });
13161
+ }
13162
+ return {
13163
+ ...menu,
13164
+ role_rights: mappedPermissions, // Use only mapped permissions
13165
+ exceptions: [],
13166
+ _permissionValues: permissionValues // Pre-computed values
13167
+ };
13168
+ });
13169
+ // Update menu rights map
13170
+ this.menuRightsMap.update(map => {
13171
+ const newMap = {
13172
+ ...map,
13173
+ [mappingIndex.toString()]: menuRights
13174
+ };
13175
+ console.log('🗺️ Updated menu rights map:', newMap);
13176
+ return newMap;
13177
+ });
13178
+ console.log('📊 Processed menu rights count:', menuRights.length);
13179
+ console.log('📋 Menu rights data:', menuRights);
13180
+ // Initialize entity mapping exceptions array if not exists
13181
+ this.entityMappings.update(mappings => {
13182
+ const updatedMappings = [...mappings];
13183
+ if (!updatedMappings[mappingIndex].exceptions) {
13184
+ updatedMappings[mappingIndex].exceptions = [];
13185
+ }
13186
+ return updatedMappings;
13187
+ });
13188
+ console.log('✅ Menu rights loaded for mapping', mappingIndex);
13189
+ // Force refresh the grid to show updated permission states
13190
+ setTimeout(() => {
13191
+ this.cdr.detectChanges();
13192
+ // Also update the grid configuration to ensure data refresh
13193
+ this.updateMenuRightsGridData(mappingIndex);
13194
+ }, 100);
13195
+ }
13196
+ else {
13197
+ console.warn('⚠️ No menu data received from API');
13198
+ this.notificationService.error('No menu data received from server', {
13199
+ title: 'Load Failed',
13200
+ duration: 5000
13201
+ });
13202
+ }
13203
+ this.loading.set(false);
12481
13204
  },
12482
- {
12483
- menu_id: 'dashboard',
12484
- menu_name: 'Dashboard',
12485
- menu_code: 'DASH',
12486
- role_rights: ['read'],
12487
- exceptions: []
13205
+ error: (error) => {
13206
+ console.error('❌ Error loading menu rights:', error);
13207
+ this.notificationService.error('Failed to load menu rights', {
13208
+ title: 'Load Failed',
13209
+ duration: 5000
13210
+ });
13211
+ this.loading.set(false);
12488
13212
  }
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
13213
  });
12502
- console.log('Menu rights loaded for mapping', mappingIndex);
12503
13214
  }
12504
13215
  refreshMenuRights(mappingIndex) {
12505
13216
  this.clearMenuRightsForMapping(mappingIndex);
12506
13217
  this.loadMenuRights(mappingIndex);
12507
13218
  }
12508
13219
  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`);
13220
+ // Clear exceptions from entity mapping
13221
+ this.entityMappings.update(mappings => {
13222
+ const updatedMappings = [...mappings];
13223
+ updatedMappings[mappingIndex].exceptions = [];
13224
+ return updatedMappings;
12516
13225
  });
12517
13226
  // Clear from menu rights map
12518
13227
  this.menuRightsMap.update(map => {
@@ -12521,6 +13230,75 @@ class CideCoreUserCreateComponent {
12521
13230
  return updatedMap;
12522
13231
  });
12523
13232
  }
13233
+ /**
13234
+ * Load user rights type ID from general master types
13235
+ */
13236
+ loadUserRightsTypeId() {
13237
+ this.generalMasterTypeService.getTypeList({
13238
+ sygmt_code: "user_rights"
13239
+ })
13240
+ .pipe(takeUntilDestroyed(this.destroyRef))
13241
+ .subscribe({
13242
+ next: (response) => {
13243
+ if (response?.success && response.data) {
13244
+ const userRightsType = response.data.find(type => type.sygmt_code === 'user_rights' || type.sygmt_title?.toLowerCase().includes('user_rights'));
13245
+ if (userRightsType) {
13246
+ this.userRightsTypeId.set(userRightsType._id || null);
13247
+ this.loadPermissions();
13248
+ }
13249
+ else {
13250
+ this.notificationService.error('User rights type not found in general master types', {
13251
+ title: 'Configuration Error',
13252
+ duration: 5000
13253
+ });
13254
+ }
13255
+ }
13256
+ },
13257
+ error: (err) => {
13258
+ this.notificationService.error('Failed to load user rights type', {
13259
+ title: 'Load Failed',
13260
+ duration: 5000
13261
+ });
13262
+ }
13263
+ });
13264
+ }
13265
+ /**
13266
+ * Load permissions from general master
13267
+ */
13268
+ loadPermissions() {
13269
+ const typeId = this.userRightsTypeId();
13270
+ if (!typeId) {
13271
+ this.notificationService.error('User rights type not found. Please ensure the "user_rights" type exists in general master types.', {
13272
+ title: 'Configuration Error',
13273
+ duration: 5000
13274
+ });
13275
+ return;
13276
+ }
13277
+ const payload = { sygms_id_sygmt: typeId };
13278
+ this.CideCoreGeneralMasterService.getMasterList(payload)
13279
+ .pipe(takeUntilDestroyed(this.destroyRef))
13280
+ .subscribe({
13281
+ next: (response) => {
13282
+ if (response?.success && response.data) {
13283
+ this.permissions.set(response.data);
13284
+ }
13285
+ else {
13286
+ this.permissions.set([]);
13287
+ this.notificationService.error('No permissions found. Please ensure permissions are configured in general master.', {
13288
+ title: 'Configuration Error',
13289
+ duration: 5000
13290
+ });
13291
+ }
13292
+ },
13293
+ error: (err) => {
13294
+ this.permissions.set([]);
13295
+ this.notificationService.error('Failed to load permissions from general master. Please check your configuration.', {
13296
+ title: 'Load Failed',
13297
+ duration: 5000
13298
+ });
13299
+ }
13300
+ });
13301
+ }
12524
13302
  hasRoleRight(menuRight, permission) {
12525
13303
  return menuRight.role_rights.includes(permission);
12526
13304
  }
@@ -12658,6 +13436,62 @@ class CideCoreUserCreateComponent {
12658
13436
  uploadType: 'user_profile_photo',
12659
13437
  };
12660
13438
  }
13439
+ /**
13440
+ * Get upload data for document files with group ID
13441
+ */
13442
+ getDocumentUploadData(documentIndex) {
13443
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
13444
+ const photoGroupId = documentFormGroup?.get('syusd_photo_group_id_cyfm')?.value;
13445
+ const documentType = documentFormGroup?.get('syusd_document_type_id_sygms')?.value;
13446
+ const documentNumber = documentFormGroup?.get('syusd_doc_number')?.value;
13447
+ // Get document type name for better tagging
13448
+ const documentTypeName = this.documentTypeOptions().find(opt => opt._id === documentType)?.sygms_title || 'Document';
13449
+ return {
13450
+ altText: `${documentTypeName} - ${documentNumber || 'Document'}`,
13451
+ userId: this.appState.getCurrentUser()?._id || '',
13452
+ groupId: photoGroupId, // Use photo group ID or generate one
13453
+ permissions: ['read', 'write'],
13454
+ tags: ['user', 'document', documentTypeName.toLowerCase(), 'file'],
13455
+ uploadType: 'user_document',
13456
+ documentIndex: documentIndex,
13457
+ documentType: documentType,
13458
+ documentNumber: documentNumber
13459
+ };
13460
+ }
13461
+ /**
13462
+ * Handle document upload success
13463
+ * For multiple file upload, uploadResponse is the group ID
13464
+ */
13465
+ onDocumentUploadSuccess(groupId, documentIndex) {
13466
+ console.log(`📎 Document upload success for document ${documentIndex} with group ID:`, groupId);
13467
+ // Update the photo group ID in the form
13468
+ const documentFormGroup = this.documentsFormArray.at(documentIndex);
13469
+ if (documentFormGroup && groupId) {
13470
+ documentFormGroup.get('syusd_photo_group_id_cyfm')?.setValue(groupId);
13471
+ console.log(`📎 Updated photo group ID for document ${documentIndex}:`, groupId);
13472
+ }
13473
+ // For multiple file upload, we don't track individual files here
13474
+ // The files are managed by the group ID on the server
13475
+ // Clear any existing file tracking since we now use group ID
13476
+ documentFormGroup._uploadedFiles = [];
13477
+ }
13478
+ /**
13479
+ * Handle document upload error
13480
+ */
13481
+ onDocumentUploadError(error, documentIndex) {
13482
+ console.error(`❌ Document upload error for document ${documentIndex}:`, error);
13483
+ this.notificationService.error(`Failed to upload document file: ${error?.message || 'Unknown error'}`, {
13484
+ title: 'Upload Failed',
13485
+ duration: 5000
13486
+ });
13487
+ }
13488
+ /**
13489
+ * Handle document upload progress
13490
+ */
13491
+ onDocumentUploadProgress(progress, documentIndex) {
13492
+ console.log(`📊 Document upload progress for document ${documentIndex}: ${progress}%`);
13493
+ // You can add progress indication here if needed
13494
+ }
12661
13495
  /**
12662
13496
  * Load profile photo preview for existing photos
12663
13497
  */
@@ -12751,6 +13585,11 @@ class CideCoreUserCreateComponent {
12751
13585
  this.documents.update(docs => [...docs, newDocumentGroup.value]);
12752
13586
  }
12753
13587
  removeDocument(index) {
13588
+ // Clean up uploaded files for this document
13589
+ const documentFormGroup = this.documentsFormArray.at(index);
13590
+ if (documentFormGroup) {
13591
+ documentFormGroup._uploadedFiles = [];
13592
+ }
12754
13593
  // Remove the document from the FormArray
12755
13594
  this.documentsFormArray.removeAt(index);
12756
13595
  // Update the documents signal to keep UI in sync
@@ -12797,12 +13636,14 @@ class CideCoreUserCreateComponent {
12797
13636
  }
12798
13637
  if (this.userMasterForm.valid) {
12799
13638
  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;
13639
+ // Prepare form data with entity mappings and exceptions
13640
+ const { core_entity_mapping, core_user_contact_addresses, core_user_documents, core_user_family_details, ...auth_user_mst } = this.userMasterForm.value;
13641
+ // Collect exceptions from all entity mappings
13642
+ const core_user_role_exceptions = this.collectRoleExceptions();
12802
13643
  const formData = {
12803
13644
  auth_user_mst: auth_user_mst,
12804
13645
  core_entity_mapping: core_entity_mapping || [],
12805
- menu_rights: this.menuRightsMap() || {},
13646
+ core_user_role_exceptions: core_user_role_exceptions,
12806
13647
  core_user_contact_addresses: core_user_contact_addresses || [],
12807
13648
  core_user_documents: core_user_documents || [],
12808
13649
  core_user_family_details: core_user_family_details || [],
@@ -12826,7 +13667,7 @@ class CideCoreUserCreateComponent {
12826
13667
  console.log('🔐 Encrypting password for edit mode...');
12827
13668
  const originalPassword = dataWithPassword.user_password;
12828
13669
  dataWithPassword.user_password = customEncrypt(dataWithPassword.user_password);
12829
- console.log('✅ Password encrypted for edit mode:', { originalLength: originalPassword.length, encryptedLength: dataWithPassword.user_password.length });
13670
+ console.log('✅ Password encrypted for edit mode:', { originalLength: originalPassword, encryptedLength: customDecrypt(dataWithPassword.user_password), dataWithPassword: dataWithPassword.user_password });
12830
13671
  }
12831
13672
  formData.auth_user_mst = dataWithPassword;
12832
13673
  }
@@ -12838,15 +13679,12 @@ class CideCoreUserCreateComponent {
12838
13679
  console.log('🔐 Encrypting password for create mode...');
12839
13680
  const originalPassword = dataWithPassword.user_password;
12840
13681
  dataWithPassword.user_password = customEncrypt(dataWithPassword.user_password);
12841
- console.log('✅ Password encrypted for create mode:', { originalLength: originalPassword.length, encryptedLength: dataWithPassword.user_password.length });
13682
+ console.log('✅ Password encrypted for create mode:', { originalLength: originalPassword, encryptedLength: dataWithPassword.user_password.length });
12842
13683
  }
12843
13684
  formData.auth_user_mst = dataWithPassword;
12844
13685
  }
12845
13686
  // Log final form data being sent (without password for security)
12846
13687
  const logData = { ...formData };
12847
- if (logData.auth_user_mst.user_password) {
12848
- logData.auth_user_mst.user_password = '***ENCRYPTED***';
12849
- }
12850
13688
  console.log('📤 Sending form data to server:', logData);
12851
13689
  // Use the service to save user master
12852
13690
  this.userMasterService.saveUpdateUserMaster(logData)
@@ -12855,19 +13693,28 @@ class CideCoreUserCreateComponent {
12855
13693
  console.log('✅ User master saved successfully:', response);
12856
13694
  this.loading.set(false);
12857
13695
  if (this.isEditMode()) {
12858
- // In edit mode, show success message and optionally navigate back
13696
+ // In edit mode, show success notification
13697
+ this.notificationService.success('User updated successfully! All changes have been saved.', {
13698
+ title: 'User Updated',
13699
+ duration: 5000
13700
+ });
12859
13701
  console.log('User updated successfully');
12860
- // Optionally navigate back to user list
12861
- // this.goBackToUserList();
12862
13702
  }
12863
13703
  else {
12864
- // In create mode, reset form for new user
13704
+ // In create mode, show success notification and reset form for new user
13705
+ this.notificationService.success('User created successfully! You can now create another user.', {
13706
+ title: 'User Created',
13707
+ duration: 5000
13708
+ });
12865
13709
  this.resetForm();
12866
13710
  }
12867
13711
  },
12868
13712
  error: (error) => {
12869
13713
  console.error('❌ Error saving user master:', error);
12870
- this.error.set('Failed to save user. Please try again.');
13714
+ this.notificationService.error('Failed to save user. Please try again.', {
13715
+ title: 'Save Failed',
13716
+ duration: 5000
13717
+ });
12871
13718
  this.loading.set(false);
12872
13719
  }
12873
13720
  });
@@ -13326,6 +14173,37 @@ class CideCoreUserCreateComponent {
13326
14173
  }
13327
14174
  });
13328
14175
  }
14176
+ /**
14177
+ * Load menu options from API
14178
+ */
14179
+ loadMenuOptions() {
14180
+ const requestBody = {
14181
+ pageIndex: 0,
14182
+ pageSize: 1000, // Load all menus
14183
+ total: 0,
14184
+ query: '',
14185
+ sort: {
14186
+ order: 'asc',
14187
+ key: 'syme_order_by'
14188
+ }
14189
+ };
14190
+ this.menuService.getMenuList(requestBody).subscribe({
14191
+ next: (response) => {
14192
+ if (response?.success) {
14193
+ console.log('🎭 Menu options loaded:', response.data);
14194
+ this.menuOptions.set(response.data || []);
14195
+ }
14196
+ else {
14197
+ console.error('❌ Failed to load menu options:', response);
14198
+ this.menuOptions.set([]);
14199
+ }
14200
+ },
14201
+ error: (error) => {
14202
+ console.error('❌ Error loading menu options:', error);
14203
+ this.menuOptions.set([]);
14204
+ }
14205
+ });
14206
+ }
13329
14207
  /**
13330
14208
  * Load dropdown data for existing addresses in edit mode
13331
14209
  */
@@ -13343,7 +14221,7 @@ class CideCoreUserCreateComponent {
13343
14221
  });
13344
14222
  }
13345
14223
  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"] }] });
14224
+ 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 <!-- Toast Notifications -->\n <cide-ele-toast-notification></cide-ele-toast-notification>\n \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\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-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 @if (!mapping?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\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 @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 <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (isAddressOwner(i)) {\n <button cideEleButton variant=\"secondary\" size=\"xs\" type=\"button\" (click)=\"shareAddress(i)\"\n leftIcon=\"share\" class=\"tw-text-blue-600 hover:tw-text-blue-700\">\n Share\n </button>\n }\n @if (!address?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\n </div>\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 <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 @if (!doc?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\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 </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 \n <!-- File Upload Input -->\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 class=\"tw-mb-3\"\n size=\"sm\">\n </cide-ele-file-input>\n\n <!-- Upload Status -->\n <!-- Upload status is now handled by the file input component itself -->\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section - Compact Design -->\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-3 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"sm\" 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-lg tw-mb-4 tw-overflow-hidden tw-transition-all tw-duration-200 hover:tw-shadow-md tw-shadow-sm\">\n \n <!-- Compact Header -->\n <div class=\"tw-bg-gray-50 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-medium\">Family Member {{ i + 1 }}</h4>\n @if (!family?._id) {\n <button cideEleButton variant=\"danger\" size=\"xs\" type=\"button\" (click)=\"removeFamilyDetail(i)\" leftIcon=\"delete\">\n Remove\n </button>\n }\n </div>\n \n <!-- Compact Form Content - 3 inputs per row -->\n <div class=\"tw-p-4\">\n <!-- Row 1: Name, User, and Combined Relationship/Active Status (33.33% each) -->\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=\"Family Member Name\" formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"sm\">\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=\"sm\"\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\n <!-- Combined Relationship and Active Status (33.33%) -->\n <div class=\"tw-flex tw-flex-row tw-gap-2 tw-items-end\">\n <div class=\"tw-flex-1\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\" placeholder=\"Select relationship\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-pt-1 tw-flex-shrink-0\">\n <cide-ele-input formControlName=\"syfdl_isactive\" type=\"checkbox\" label=\"Active\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n\n <!-- Row 2: Blood Group, DOB, and Phone -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 xl:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\" placeholder=\"Select blood group\" size=\"sm\" valueKey=\"_id\"\n labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Date of Birth\" formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"sm\"\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=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 3: Email, Email ID, and Contact Number -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 xl:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\" type=\"email\"\n placeholder=\"Enter contact email\" size=\"sm\">\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=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\" type=\"tel\"\n placeholder=\"Enter contact number\" size=\"sm\">\n </cide-ele-input>\n </div>\n\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", "showFloatingUploader", "floatingUploaderGroupId"], 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: "component", type: CideEleToastNotificationComponent, selector: "cide-ele-toast-notification" }] });
13347
14225
  }
13348
14226
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserCreateComponent, decorators: [{
13349
14227
  type: Component,
@@ -13359,8 +14237,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
13359
14237
  CideEleFileInputComponent,
13360
14238
  CideEleFileImageDirective,
13361
14239
  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>" }]
14240
+ CideEleDataGridComponent,
14241
+ CideEleToastNotificationComponent
14242
+ ], 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 <!-- Toast Notifications -->\n <cide-ele-toast-notification></cide-ele-toast-notification>\n \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\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-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 @if (!mapping?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeEntityMapping(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\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 @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 <div class=\"tw-flex tw-items-center tw-gap-2\">\n @if (isAddressOwner(i)) {\n <button cideEleButton variant=\"secondary\" size=\"xs\" type=\"button\" (click)=\"shareAddress(i)\"\n leftIcon=\"share\" class=\"tw-text-blue-600 hover:tw-text-blue-700\">\n Share\n </button>\n }\n @if (!address?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeContactAddress(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\n </div>\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 <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 @if (!doc?._id) {\n <button cideEleButton variant=\"danger\" size=\"sm\" type=\"button\" (click)=\"removeDocument(i)\"\n leftIcon=\"delete\">\n Remove\n </button>\n }\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 </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 \n <!-- File Upload Input -->\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 class=\"tw-mb-3\"\n size=\"sm\">\n </cide-ele-file-input>\n\n <!-- Upload Status -->\n <!-- Upload status is now handled by the file input component itself -->\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @case ('family') {\n <!-- Family Details Section - Compact Design -->\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-3 tw-gap-4\">\n <button cideEleButton variant=\"primary\" size=\"sm\" 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-lg tw-mb-4 tw-overflow-hidden tw-transition-all tw-duration-200 hover:tw-shadow-md tw-shadow-sm\">\n \n <!-- Compact Header -->\n <div class=\"tw-bg-gray-50 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-medium\">Family Member {{ i + 1 }}</h4>\n @if (!family?._id) {\n <button cideEleButton variant=\"danger\" size=\"xs\" type=\"button\" (click)=\"removeFamilyDetail(i)\" leftIcon=\"delete\">\n Remove\n </button>\n }\n </div>\n \n <!-- Compact Form Content - 3 inputs per row -->\n <div class=\"tw-p-4\">\n <!-- Row 1: Name, User, and Combined Relationship/Active Status (33.33% each) -->\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=\"Family Member Name\" formControlName=\"syfdl_family_member_name\"\n placeholder=\"Enter family member full name\" size=\"sm\">\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=\"sm\"\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\n <!-- Combined Relationship and Active Status (33.33%) -->\n <div class=\"tw-flex tw-flex-row tw-gap-2 tw-items-end\">\n <div class=\"tw-flex-1\">\n <cide-ele-select label=\"Relationship\" [options]=\"relationshipOptions()\"\n formControlName=\"syfdl_relationship_id_sygms\" placeholder=\"Select relationship\" size=\"sm\"\n valueKey=\"_id\" labelKey=\"sygms_title\">\n </cide-ele-select>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-pt-1 tw-flex-shrink-0\">\n <cide-ele-input formControlName=\"syfdl_isactive\" type=\"checkbox\" label=\"Active\" size=\"sm\">\n </cide-ele-input>\n </div>\n </div>\n </div>\n\n <!-- Row 2: Blood Group, DOB, and Phone -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 xl:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-select label=\"Blood Group\" [options]=\"bloodGroupOptions()\"\n formControlName=\"syfdl_blood_group_sygms\" placeholder=\"Select blood group\" size=\"sm\" valueKey=\"_id\"\n labelKey=\"sygms_title\">\n </cide-ele-select>\n\n <cide-ele-input label=\"Date of Birth\" formControlName=\"syfdl_family_member_dob\" type=\"date\" size=\"sm\"\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=\"sm\">\n </cide-ele-input>\n </div>\n\n <!-- Row 3: Email, Email ID, and Contact Number -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 xl:tw-grid-cols-3 tw-gap-3 tw-mb-3\">\n <cide-ele-input label=\"Contact Email\" formControlName=\"syfdl_contact_email\" type=\"email\"\n placeholder=\"Enter contact email\" size=\"sm\">\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=\"sm\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Contact Number\" formControlName=\"syfdl_contact_number\" type=\"tel\"\n placeholder=\"Enter contact number\" size=\"sm\">\n </cide-ele-input>\n </div>\n\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
14243
  }], ctorParameters: () => [] });
13365
14244
 
13366
14245
  var userCreate_component = /*#__PURE__*/Object.freeze({
@@ -13871,7 +14750,7 @@ class CideCoreUserListComponent {
13871
14750
  }
13872
14751
  }
13873
14752
  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"] }] });
14753
+ 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
14754
  }
13876
14755
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideCoreUserListComponent, decorators: [{
13877
14756
  type: Component,
@@ -13883,7 +14762,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
13883
14762
  CideSelectComponent,
13884
14763
  CideEleDataGridComponent,
13885
14764
  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"] }]
14765
+ ], 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
14766
  }], propDecorators: { gridComponent: [{
13888
14767
  type: ViewChild,
13889
14768
  args: [CideEleDataGridComponent]