cloud-ide-layout 1.0.65 → 1.0.67

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.
Files changed (13) hide show
  1. package/fesm2022/{cloud-ide-layout-cloud-ide-layout-B6GmMuGs.mjs → cloud-ide-layout-cloud-ide-layout-Dociv0e8.mjs} +50 -93
  2. package/fesm2022/cloud-ide-layout-cloud-ide-layout-Dociv0e8.mjs.map +1 -0
  3. package/fesm2022/{cloud-ide-layout-drawer-theme.component-CuGm3ZnU.mjs → cloud-ide-layout-drawer-theme.component-By_WtOQ-.mjs} +2 -2
  4. package/fesm2022/{cloud-ide-layout-drawer-theme.component-CuGm3ZnU.mjs.map → cloud-ide-layout-drawer-theme.component-By_WtOQ-.mjs.map} +1 -1
  5. package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Dny7ygEb.mjs → cloud-ide-layout-floating-entity-selection.component-Ckh8ecVF.mjs} +2 -2
  6. package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Dny7ygEb.mjs.map → cloud-ide-layout-floating-entity-selection.component-Ckh8ecVF.mjs.map} +1 -1
  7. package/fesm2022/{cloud-ide-layout-home-wrapper.component-BjZwFaSK.mjs → cloud-ide-layout-home-wrapper.component-ZllC_HLn.mjs} +2 -2
  8. package/fesm2022/{cloud-ide-layout-home-wrapper.component-BjZwFaSK.mjs.map → cloud-ide-layout-home-wrapper.component-ZllC_HLn.mjs.map} +1 -1
  9. package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-DnT1QLA7.mjs → cloud-ide-layout-sidedrawer-notes.component-6ilViFo8.mjs} +2 -2
  10. package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-DnT1QLA7.mjs.map → cloud-ide-layout-sidedrawer-notes.component-6ilViFo8.mjs.map} +1 -1
  11. package/fesm2022/cloud-ide-layout.mjs +1 -1
  12. package/package.json +1 -1
  13. package/fesm2022/cloud-ide-layout-cloud-ide-layout-B6GmMuGs.mjs.map +0 -1
@@ -1266,7 +1266,7 @@ class CideLytFloatingEntitySelectionService {
1266
1266
  }
1267
1267
  try {
1268
1268
  // Use relative import to avoid circular dependency
1269
- const module = await import('./cloud-ide-layout-floating-entity-selection.component-Dny7ygEb.mjs');
1269
+ const module = await import('./cloud-ide-layout-floating-entity-selection.component-Ckh8ecVF.mjs');
1270
1270
  if (module.CideLytFloatingEntitySelectionComponent) {
1271
1271
  this.containerService.registerComponent('entity-selection-header', module.CideLytFloatingEntitySelectionComponent);
1272
1272
  console.log('✅ Entity selection component registered successfully');
@@ -1553,20 +1553,21 @@ class CideLytHeaderWrapperComponent {
1553
1553
  }
1554
1554
  /**
1555
1555
  * Load notifications from API
1556
- * @param showReadOnly - If true, only load read notifications. If false, load all.
1556
+ * @param showAll - If true, show all notifications (read + unread). If false, show only unread.
1557
1557
  */
1558
- loadNotifications(showReadOnly = false) {
1558
+ loadNotifications(showAll = false) {
1559
1559
  try {
1560
1560
  // Get notifications from WebSocket service (real-time)
1561
1561
  const wsNotifications = this.wsNotificationService?.allNotifications() || [];
1562
1562
  console.log('[Notifications] WebSocket notifications:', wsNotifications.length);
1563
1563
  // Load from API to get all notifications (including read status)
1564
- // By default, we can filter to show unread first, but load all for "View All"
1565
1564
  const params = {
1566
- pageSize: 20
1565
+ pageSize: showAll ? 100 : 20
1567
1566
  };
1568
- // Optionally filter by status if we only want unread
1569
- // Note: We load all and filter client-side for better UX
1567
+ // If not showing all, filter to exclude read notifications
1568
+ if (!showAll) {
1569
+ // We'll filter client-side after loading to ensure we get accurate read status
1570
+ }
1570
1571
  this.notificationApiService.getNotifications(params).subscribe({
1571
1572
  next: (response) => {
1572
1573
  console.log('[Notifications] API response:', response);
@@ -1588,6 +1589,11 @@ class CideLytHeaderWrapperComponent {
1588
1589
  isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
1589
1590
  }));
1590
1591
  console.log('[Notifications] Converted API payloads:', apiPayloads.length);
1592
+ console.log('[Notifications] Read status breakdown:', {
1593
+ total: apiPayloads.length,
1594
+ read: apiPayloads.filter(n => n.isRead).length,
1595
+ unread: apiPayloads.filter(n => !n.isRead).length
1596
+ });
1591
1597
  // Merge WebSocket and API notifications (API takes priority for read status)
1592
1598
  const mergedNotifications = [];
1593
1599
  // Add API notifications first (they have read status)
@@ -1600,29 +1606,31 @@ class CideLytHeaderWrapperComponent {
1600
1606
  mergedNotifications.push({ ...wsNotif, isRead: false });
1601
1607
  }
1602
1608
  });
1603
- // Sort by timestamp (newest first)
1604
- mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
1605
- console.log('[Notifications] Total merged notifications:', mergedNotifications.length);
1606
- // Update WebSocket service with read status
1607
- if (this.wsNotificationService) {
1608
- // Update unread count based on read status
1609
- const unread = mergedNotifications.filter(n => !n.isRead);
1610
- // Note: WebSocket service manages its own unread count, but we sync here
1609
+ // Filter out read notifications if not showing all
1610
+ let filteredNotifications = mergedNotifications;
1611
+ if (!showAll) {
1612
+ filteredNotifications = mergedNotifications.filter(n => !n.isRead);
1613
+ console.log('[Notifications] Filtered to unread only:', filteredNotifications.length);
1611
1614
  }
1612
- this.notifications.set(mergedNotifications);
1615
+ // Sort by timestamp (newest first)
1616
+ filteredNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
1617
+ console.log('[Notifications] Total notifications to display:', filteredNotifications.length);
1618
+ this.notifications.set(filteredNotifications);
1613
1619
  this.updateNotificationDropdown();
1614
1620
  }
1615
1621
  else {
1616
1622
  console.warn('[Notifications] API response invalid, using WebSocket notifications only');
1617
- // Fallback to WebSocket notifications only
1618
- this.notifications.set(wsNotifications);
1623
+ // Fallback to WebSocket notifications only (filter to unread if needed)
1624
+ const filtered = showAll ? wsNotifications : wsNotifications.filter(n => !n.isRead);
1625
+ this.notifications.set(filtered);
1619
1626
  this.updateNotificationDropdown();
1620
1627
  }
1621
1628
  },
1622
1629
  error: (error) => {
1623
1630
  console.error('[Notifications] Error loading from API:', error);
1624
- // Fallback to WebSocket notifications only
1625
- this.notifications.set(wsNotifications);
1631
+ // Fallback to WebSocket notifications only (filter to unread if needed)
1632
+ const filtered = showAll ? wsNotifications : wsNotifications.filter(n => !n.isRead);
1633
+ this.notifications.set(filtered);
1626
1634
  this.updateNotificationDropdown();
1627
1635
  }
1628
1636
  });
@@ -1904,8 +1912,8 @@ class CideLytHeaderWrapperComponent {
1904
1912
  this.notificationApiService.markAsRead(notificationId).subscribe({
1905
1913
  next: (response) => {
1906
1914
  console.log('[Notifications] Marked as read successfully:', response);
1907
- // Reload notifications to update unread count
1908
- this.loadNotifications();
1915
+ // Reload notifications to update unread count (only show unread)
1916
+ this.loadNotifications(false); // false = only show unread
1909
1917
  },
1910
1918
  error: (error) => {
1911
1919
  console.error('[Notifications] Error marking notification as read:', error);
@@ -1928,8 +1936,14 @@ class CideLytHeaderWrapperComponent {
1928
1936
  this.notificationApiService.markAllAsRead().subscribe({
1929
1937
  next: (response) => {
1930
1938
  console.log('[Notifications] All notifications marked as read successfully:', response);
1931
- // Reload notifications to update unread count
1932
- this.loadNotifications();
1939
+ // Clear current notifications since they're all read now
1940
+ // This will show empty state or only new unread notifications
1941
+ this.notifications.set([]);
1942
+ this.updateNotificationDropdown();
1943
+ // Reload after a short delay to get updated state (will only show unread)
1944
+ setTimeout(() => {
1945
+ this.loadNotifications(false); // false = only show unread
1946
+ }, 500);
1933
1947
  },
1934
1948
  error: (error) => {
1935
1949
  console.error('[Notifications] Error marking all as read:', error);
@@ -1940,7 +1954,7 @@ class CideLytHeaderWrapperComponent {
1940
1954
  url: error?.url
1941
1955
  });
1942
1956
  // Still reload to get updated state
1943
- this.loadNotifications();
1957
+ this.loadNotifications(false); // false = only show unread
1944
1958
  }
1945
1959
  });
1946
1960
  }
@@ -1954,19 +1968,13 @@ class CideLytHeaderWrapperComponent {
1954
1968
  this.notificationApiService.markAllAsRead().subscribe({
1955
1969
  next: (response) => {
1956
1970
  console.log('[Notifications] All notifications marked as read:', response);
1957
- // Filter current notifications to mark them as read locally
1958
- const currentNotifs = this.notifications();
1959
- const updatedNotifs = currentNotifs.map(notif => ({
1960
- ...notif,
1961
- isRead: true
1962
- }));
1963
- // Clear notifications from view (they're all read now)
1971
+ // Clear notifications from view immediately (they're all read now)
1964
1972
  this.notifications.set([]);
1965
1973
  this.updateNotificationDropdown();
1966
1974
  // Reload after a short delay to get updated state from server
1967
1975
  // This will show empty or only new unread notifications
1968
1976
  setTimeout(() => {
1969
- this.loadNotifications();
1977
+ this.loadNotifications(false); // false = only show unread
1970
1978
  }, 500);
1971
1979
  },
1972
1980
  error: (error) => {
@@ -1978,7 +1986,7 @@ class CideLytHeaderWrapperComponent {
1978
1986
  url: error?.url
1979
1987
  });
1980
1988
  // Still try to reload
1981
- this.loadNotifications();
1989
+ this.loadNotifications(false); // false = only show unread
1982
1990
  }
1983
1991
  });
1984
1992
  }
@@ -1988,60 +1996,9 @@ class CideLytHeaderWrapperComponent {
1988
1996
  */
1989
1997
  loadAllNotifications() {
1990
1998
  try {
1991
- const wsNotifications = this.wsNotificationService?.allNotifications() || [];
1992
1999
  console.log('[Notifications] Loading all notifications (View All)');
1993
- // Load more notifications from API (increase pageSize)
1994
- this.notificationApiService.getNotifications({
1995
- pageSize: 100 // Load more for "View All"
1996
- }).subscribe({
1997
- next: (response) => {
1998
- console.log('[Notifications] All notifications API response:', response);
1999
- if (response && response.success && response.data) {
2000
- // Convert server notifications to notification payloads
2001
- const apiPayloads = response.data.map((notif) => ({
2002
- id: String(notif._id),
2003
- type: notif.not_type || 'info',
2004
- category: notif.not_category,
2005
- title: notif.not_title,
2006
- message: notif.not_message,
2007
- data: notif.not_data,
2008
- action_url: notif.not_action_url,
2009
- action_label: notif.not_action_label,
2010
- priority: notif.not_priority || 'normal',
2011
- created_at: new Date(notif.not_created_at),
2012
- timestamp: new Date(notif.not_created_at),
2013
- isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
2014
- }));
2015
- // Merge WebSocket and API notifications
2016
- const mergedNotifications = [];
2017
- // Add API notifications first
2018
- apiPayloads.forEach(apiNotif => {
2019
- mergedNotifications.push(apiNotif);
2020
- });
2021
- // Add WebSocket notifications that aren't in API
2022
- wsNotifications.forEach(wsNotif => {
2023
- if (!mergedNotifications.find(n => n.id === wsNotif.id)) {
2024
- mergedNotifications.push({ ...wsNotif, isRead: false });
2025
- }
2026
- });
2027
- // Sort by timestamp (newest first)
2028
- mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
2029
- console.log('[Notifications] Total notifications loaded:', mergedNotifications.length);
2030
- this.notifications.set(mergedNotifications);
2031
- this.updateNotificationDropdown();
2032
- }
2033
- else {
2034
- console.warn('[Notifications] API response invalid');
2035
- this.notifications.set(wsNotifications);
2036
- this.updateNotificationDropdown();
2037
- }
2038
- },
2039
- error: (error) => {
2040
- console.error('[Notifications] Error loading all notifications:', error);
2041
- this.notifications.set(wsNotifications);
2042
- this.updateNotificationDropdown();
2043
- }
2044
- });
2000
+ // Load all notifications (read + unread) for "View All"
2001
+ this.loadNotifications(true); // true = show all (read + unread)
2045
2002
  }
2046
2003
  catch (error) {
2047
2004
  console.error('[Notifications] Error in loadAllNotifications:', error);
@@ -2431,12 +2388,12 @@ class CideLytHeaderWrapperComponent {
2431
2388
  }
2432
2389
  }
2433
2390
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2434
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", viewQueries: [{ propertyName: "triggerTemplate", first: true, predicate: ["triggerTemplate"], descendants: true }, { propertyName: "financialYearTriggerTemplate", first: true, predicate: ["financialYearTriggerTemplate"], descendants: true }, { propertyName: "academicYearTriggerTemplate", first: true, predicate: ["academicYearTriggerTemplate"], descendants: true }, { propertyName: "notificationTriggerTemplate", first: true, predicate: ["notificationTriggerTemplate"], descendants: true }, { propertyName: "notificationDropdown", first: true, predicate: ["notificationDropdown"], descendants: true }], ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n #notificationDropdown\n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n [menuTemplate]=\"notificationMenuTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"notification-panel\">\n <!-- Header -->\n <div class=\"notification-panel-header\">\n <div class=\"notification-panel-header-left\">\n <h3 class=\"notification-panel-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-panel-unread-count\">{{ unreadCount() }}</span>\n }\n </div>\n <button \n type=\"button\" \n class=\"notification-panel-close\"\n (click)=\"closeNotificationDropdown($event)\">\n <cide-ele-icon>close</cide-ele-icon>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-panel-body\">\n @if (notifications().length === 0) {\n <div class=\"notification-empty-state\">\n <cide-ele-icon class=\"notification-empty-icon\">notifications_off</cide-ele-icon>\n <p class=\"notification-empty-text\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 15); track notif.id) {\n <div \n class=\"notification-panel-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <!-- Profile Avatar -->\n <div class=\"notification-avatar\">\n @if (getNotificationAvatar(notif)) {\n <img \n cideEleFileImage \n [fileId]=\"getNotificationAvatar(notif) || ''\"\n [altText]=\"getNotificationName(notif)\"\n class=\"notification-avatar-img\">\n } @else {\n <div class=\"notification-avatar-placeholder\">\n <cide-ele-icon>{{ getNotificationIcon(notif.type) }}</cide-ele-icon>\n </div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"notification-panel-content\">\n <div class=\"notification-panel-text\">\n <span class=\"notification-panel-name\">{{ getNotificationName(notif) }}</span>\n <span class=\"notification-panel-action\">{{ getNotificationAction(notif) }}</span>\n </div>\n <div class=\"notification-panel-time\">\n <span class=\"notification-time-full\">{{ getFullTime(notif.timestamp) }}</span>\n <span class=\"notification-time-ago\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n @if (notif.message && notif.message !== notif.title) {\n <div class=\"notification-panel-message\">\n {{ notif.message }}\n </div>\n }\n @if (notif.data?.comment) {\n <div class=\"notification-comment-bubble\">\n {{ notif.data.comment }}\n </div>\n }\n @if (notif.data?.file) {\n <div class=\"notification-file-preview\">\n <div class=\"notification-file-icon\">{{ getFileIcon(notif.data.file.type) }}</div>\n <div class=\"notification-file-info\">\n <div class=\"notification-file-name\">{{ notif.data.file.name }}</div>\n <div class=\"notification-file-size\">{{ notif.data.file.size }}</div>\n </div>\n <cide-ele-icon class=\"notification-file-download\">download</cide-ele-icon>\n </div>\n }\n @if (notif.action_label) {\n <div class=\"notification-actions-inline\">\n @if (notif.action_label.toLowerCase().includes('decline')) {\n <button type=\"button\" class=\"notification-action-btn-inline decline\">Decline</button>\n }\n @if (notif.action_label.toLowerCase().includes('accept')) {\n <button type=\"button\" class=\"notification-action-btn-inline accept\">Accept</button>\n }\n </div>\n }\n </div>\n\n <!-- Unread Indicator -->\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-panel-unread-dot\"></div>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}.notification-panel{width:100%;max-width:420px;background:#fff;border-radius:0;box-shadow:-2px 0 20px #0000001a;overflow:hidden;display:flex;flex-direction:column;max-height:80vh;border-left:1px solid #e5e7eb}.notification-panel-header{padding:20px 24px;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:10;background:#fff}.notification-panel-header-left{display:flex;align-items:center;gap:12px}.notification-panel-title{margin:0;font-size:1.25rem;font-weight:600;color:#111827;letter-spacing:-.02em}.notification-panel-unread-count{background:#3b82f6;color:#fff;padding:2px 10px;border-radius:12px;font-size:.875rem;font-weight:600;min-width:24px;text-align:center}.notification-panel-close{background:transparent;border:none;padding:4px;cursor:pointer;color:#6b7280;display:flex;align-items:center;justify-content:center;border-radius:6px;transition:all .2s ease;width:32px;height:32px}.notification-panel-close:hover{background:#f3f4f6;color:#111827}.notification-panel-close cide-ele-icon{font-size:1.25rem!important}.notification-panel-body{flex:1;overflow-y:auto;padding:0}.notification-panel-body::-webkit-scrollbar{width:8px}.notification-panel-body::-webkit-scrollbar-track{background:#f9fafb}.notification-panel-body::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:4px}.notification-panel-body::-webkit-scrollbar-thumb:hover{background:#9ca3af}.notification-empty-state{padding:60px 24px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:4rem!important;color:#d1d5db!important;margin-bottom:16px}.notification-empty-text{margin:0;font-size:1rem;color:#6b7280;font-weight:500}.notification-panel-item{display:flex;align-items:flex-start;padding:16px 24px;cursor:pointer;transition:all .2s ease;position:relative;gap:16px;border-bottom:1px solid #f3f4f6}.notification-panel-item:hover{background:#f9fafb}.notification-panel-item.unread{background:#f8fafc}.notification-panel-item.unread:hover{background:#f1f5f9}.notification-avatar{flex-shrink:0;width:48px;height:48px;border-radius:50%;overflow:hidden;background:#e5e7eb;display:flex;align-items:center;justify-content:center}.notification-avatar-img{width:100%;height:100%;object-fit:cover}.notification-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;align-items:center;justify-content:center}.notification-avatar-placeholder cide-ele-icon{font-size:1.5rem!important;color:#fff!important}.notification-panel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}.notification-panel-text{font-size:.9375rem;color:#111827;line-height:1.5}.notification-panel-name{font-weight:600;color:#111827}.notification-panel-action{color:#4b5563;font-weight:400}.notification-panel-time{display:flex;gap:8px;align-items:center;font-size:.8125rem;color:#6b7280}.notification-time-full{font-weight:500}.notification-time-ago{color:#9ca3af}.notification-panel-message{margin-top:4px;font-size:.875rem;color:#4b5563;line-height:1.5}.notification-comment-bubble{margin-top:8px;padding:12px 16px;background:#f3f4f6;border-radius:12px;border-left:3px solid #3b82f6;font-size:.875rem;color:#374151;line-height:1.6;font-style:italic}.notification-file-preview{margin-top:8px;padding:12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;display:flex;align-items:center;gap:12px}.notification-file-icon{width:40px;height:40px;background:#e5e7eb;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:600;color:#6b7280;flex-shrink:0}.notification-file-info{flex:1;min-width:0}.notification-file-name{font-size:.875rem;font-weight:500;color:#111827;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.notification-file-size{font-size:.75rem;color:#6b7280}.notification-file-download{color:#6b7280;cursor:pointer;transition:color .2s ease;flex-shrink:0}.notification-file-download:hover{color:#3b82f6}.notification-actions-inline{margin-top:8px;display:flex;gap:8px}.notification-action-btn-inline{padding:6px 16px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.875rem;font-weight:500;cursor:pointer;transition:all .2s ease}.notification-action-btn-inline.decline{color:#6b7280}.notification-action-btn-inline.decline:hover{background:#f3f4f6;border-color:#d1d5db}.notification-action-btn-inline.accept{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn-inline.accept:hover{background:#2563eb;border-color:#2563eb}.notification-panel-unread-dot{position:absolute;top:20px;right:24px;width:10px;height:10px;border-radius:50%;background:#3b82f6;flex-shrink:0}\n"], dependencies: [{ 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: "ngmodule", type: CommonModule }, { 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: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }] });
2391
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", viewQueries: [{ propertyName: "triggerTemplate", first: true, predicate: ["triggerTemplate"], descendants: true }, { propertyName: "financialYearTriggerTemplate", first: true, predicate: ["financialYearTriggerTemplate"], descendants: true }, { propertyName: "academicYearTriggerTemplate", first: true, predicate: ["academicYearTriggerTemplate"], descendants: true }, { propertyName: "notificationTriggerTemplate", first: true, predicate: ["notificationTriggerTemplate"], descendants: true }, { propertyName: "notificationDropdown", first: true, predicate: ["notificationDropdown"], descendants: true }], ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n #notificationDropdown\n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n [menuTemplate]=\"notificationMenuTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"tw-w-full tw-max-w-[380px] tw-min-w-[360px] tw-bg-white tw-rounded-none tw-shadow-[-2px_0_20px_rgba(0,0,0,0.1)] tw-overflow-hidden tw-flex tw-flex-col tw-max-h-[80vh] tw-border-l tw-border-l-gray-200\">\n <!-- Header -->\n <div class=\"tw-px-4 tw-py-3 tw-bg-white tw-border-b tw-border-b-gray-200 tw-flex tw-justify-between tw-items-center tw-sticky tw-top-0 tw-z-10\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h3 class=\"tw-m-0 tw-text-base tw-font-semibold tw-text-gray-900\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"tw-bg-blue-500 tw-text-white tw-px-2 tw-py-0.5 tw-rounded-full tw-text-[11px] tw-font-semibold tw-min-w-5 tw-text-center tw-leading-none\">{{ unreadCount() }}</span>\n }\n </div>\n <button \n type=\"button\" \n class=\"tw-bg-transparent tw-border-none tw-p-1 tw-cursor-pointer tw-text-gray-500 tw-flex tw-items-center tw-justify-center tw-rounded tw-transition-all tw-duration-200 tw-w-7 tw-h-7 hover:tw-bg-gray-100 hover:tw-text-gray-900\"\n (click)=\"closeNotificationDropdown($event)\">\n <cide-ele-icon class=\"!tw-text-lg\">close</cide-ele-icon>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-0 [&::-webkit-scrollbar]:tw-w-1.5 [&::-webkit-scrollbar-track]:tw-bg-gray-50 [&::-webkit-scrollbar-thumb]:tw-bg-gray-300 [&::-webkit-scrollbar-thumb]:tw-rounded [&::-webkit-scrollbar-thumb]:hover:tw-bg-gray-400\">\n @if (notifications().length === 0) {\n <div class=\"tw-py-12 tw-px-4 tw-text-center tw-text-gray-400\">\n <cide-ele-icon class=\"!tw-text-5xl !tw-text-gray-300 tw-mb-3\">notifications_off</cide-ele-icon>\n <p class=\"tw-m-0 tw-text-sm tw-text-gray-500 tw-font-medium\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 15); track notif.id) {\n <div \n class=\"tw-flex tw-items-start tw-px-4 tw-py-3 tw-cursor-pointer tw-transition-all tw-duration-200 tw-relative tw-gap-2.5 tw-border-b tw-border-b-gray-100 hover:tw-bg-gray-50\"\n [class.tw-bg-white]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <!-- Profile Avatar -->\n <div class=\"tw-flex-shrink-0 tw-w-9 tw-h-9 tw-rounded-full tw-overflow-hidden tw-bg-gray-200 tw-flex tw-items-center tw-justify-center\">\n @if (getNotificationAvatar(notif)) {\n <img \n cideEleFileImage \n [fileId]=\"getNotificationAvatar(notif) || ''\"\n [altText]=\"getNotificationName(notif)\"\n class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <div class=\"tw-w-full tw-h-full tw-bg-gradient-to-br tw-from-indigo-500 tw-to-purple-600 tw-text-white tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"!tw-text-lg !tw-text-white\">{{ getNotificationIcon(notif.type) }}</cide-ele-icon>\n </div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"tw-flex-1 tw-min-w-0 tw-flex tw-flex-col tw-gap-0.5 tw-pr-4\">\n <div class=\"tw-text-[13px] tw-text-gray-900 tw-leading-snug\">\n <span class=\"tw-font-semibold tw-text-gray-900\">{{ getNotificationName(notif) }}</span>\n <span class=\"tw-font-normal tw-text-gray-600 tw-ml-0.5\">{{ getNotificationAction(notif) }}</span>\n </div>\n <div class=\"tw-flex tw-gap-1.5 tw-items-center tw-text-[11px] tw-text-gray-500\">\n <span class=\"tw-font-medium tw-text-gray-500\">{{ getFullTime(notif.timestamp) }}</span>\n <span class=\"tw-text-gray-400 tw-font-normal\">\u2022</span>\n <span class=\"tw-text-gray-400 tw-font-normal\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n @if (notif.message && notif.message !== notif.title) {\n <div class=\"tw-mt-0.5 tw-text-[13px] tw-text-gray-600 tw-leading-snug\">\n {{ notif.message }}\n </div>\n }\n @if (notif.data?.comment) {\n <div class=\"tw-mt-1.5 tw-py-2 tw-px-3 tw-bg-gray-50 tw-rounded-md tw-border-l-3 tw-border-l-blue-500 tw-text-[12px] tw-text-gray-700 tw-leading-snug\">\n {{ notif.data.comment }}\n </div>\n }\n @if (notif.data?.file) {\n <div class=\"tw-mt-1.5 tw-py-2 tw-px-2.5 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-md tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-w-8 tw-h-8 tw-bg-gray-200 tw-rounded tw-flex tw-items-center tw-justify-center tw-text-[10px] tw-font-semibold tw-text-gray-500 tw-flex-shrink-0\">{{ getFileIcon(notif.data.file.type) }}</div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <div class=\"tw-text-[12px] tw-font-medium tw-text-gray-900 tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap\">{{ notif.data.file.name }}</div>\n <div class=\"tw-text-[10px] tw-text-gray-500\">{{ notif.data.file.size }}</div>\n </div>\n <cide-ele-icon class=\"tw-text-gray-500 tw-cursor-pointer tw-transition-colors tw-duration-200 tw-flex-shrink-0 tw-text-sm hover:tw-text-blue-500\">download</cide-ele-icon>\n </div>\n }\n @if (notif.action_label) {\n <div class=\"tw-mt-1.5 tw-flex tw-gap-2\">\n @if (notif.action_label.toLowerCase().includes('decline')) {\n <button type=\"button\" class=\"tw-py-1 tw-px-3 tw-border tw-border-gray-200 tw-bg-gray-50 tw-rounded-md tw-text-[12px] tw-font-medium tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-500 hover:tw-bg-gray-100 hover:tw-border-gray-300\">Decline</button>\n }\n @if (notif.action_label.toLowerCase().includes('accept')) {\n <button type=\"button\" class=\"tw-py-1 tw-px-3 tw-border tw-border-blue-500 tw-bg-blue-500 tw-rounded-md tw-text-[12px] tw-font-medium tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-white hover:tw-bg-blue-600 hover:tw-border-blue-600\">Accept</button>\n }\n </div>\n }\n </div>\n\n <!-- Unread Indicator -->\n @if (!isNotificationRead(notif)) {\n <div class=\"tw-absolute tw-top-3.5 tw-right-4 tw-w-2 tw-h-2 tw-rounded-full tw-bg-blue-500 tw-flex-shrink-0\"></div>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"], dependencies: [{ 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: "ngmodule", type: CommonModule }, { 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: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }] });
2435
2392
  }
2436
2393
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
2437
2394
  type: Component,
2438
2395
  args: [{ selector: 'cide-lyt-header-wrapper', imports: [CideInputComponent, CommonModule, CideIconComponent,
2439
- CideEleDropdownComponent, CideEleFileImageDirective], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n #notificationDropdown\n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n [menuTemplate]=\"notificationMenuTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"notification-panel\">\n <!-- Header -->\n <div class=\"notification-panel-header\">\n <div class=\"notification-panel-header-left\">\n <h3 class=\"notification-panel-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-panel-unread-count\">{{ unreadCount() }}</span>\n }\n </div>\n <button \n type=\"button\" \n class=\"notification-panel-close\"\n (click)=\"closeNotificationDropdown($event)\">\n <cide-ele-icon>close</cide-ele-icon>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-panel-body\">\n @if (notifications().length === 0) {\n <div class=\"notification-empty-state\">\n <cide-ele-icon class=\"notification-empty-icon\">notifications_off</cide-ele-icon>\n <p class=\"notification-empty-text\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 15); track notif.id) {\n <div \n class=\"notification-panel-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <!-- Profile Avatar -->\n <div class=\"notification-avatar\">\n @if (getNotificationAvatar(notif)) {\n <img \n cideEleFileImage \n [fileId]=\"getNotificationAvatar(notif) || ''\"\n [altText]=\"getNotificationName(notif)\"\n class=\"notification-avatar-img\">\n } @else {\n <div class=\"notification-avatar-placeholder\">\n <cide-ele-icon>{{ getNotificationIcon(notif.type) }}</cide-ele-icon>\n </div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"notification-panel-content\">\n <div class=\"notification-panel-text\">\n <span class=\"notification-panel-name\">{{ getNotificationName(notif) }}</span>\n <span class=\"notification-panel-action\">{{ getNotificationAction(notif) }}</span>\n </div>\n <div class=\"notification-panel-time\">\n <span class=\"notification-time-full\">{{ getFullTime(notif.timestamp) }}</span>\n <span class=\"notification-time-ago\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n @if (notif.message && notif.message !== notif.title) {\n <div class=\"notification-panel-message\">\n {{ notif.message }}\n </div>\n }\n @if (notif.data?.comment) {\n <div class=\"notification-comment-bubble\">\n {{ notif.data.comment }}\n </div>\n }\n @if (notif.data?.file) {\n <div class=\"notification-file-preview\">\n <div class=\"notification-file-icon\">{{ getFileIcon(notif.data.file.type) }}</div>\n <div class=\"notification-file-info\">\n <div class=\"notification-file-name\">{{ notif.data.file.name }}</div>\n <div class=\"notification-file-size\">{{ notif.data.file.size }}</div>\n </div>\n <cide-ele-icon class=\"notification-file-download\">download</cide-ele-icon>\n </div>\n }\n @if (notif.action_label) {\n <div class=\"notification-actions-inline\">\n @if (notif.action_label.toLowerCase().includes('decline')) {\n <button type=\"button\" class=\"notification-action-btn-inline decline\">Decline</button>\n }\n @if (notif.action_label.toLowerCase().includes('accept')) {\n <button type=\"button\" class=\"notification-action-btn-inline accept\">Accept</button>\n }\n </div>\n }\n </div>\n\n <!-- Unread Indicator -->\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-panel-unread-dot\"></div>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}.notification-panel{width:100%;max-width:420px;background:#fff;border-radius:0;box-shadow:-2px 0 20px #0000001a;overflow:hidden;display:flex;flex-direction:column;max-height:80vh;border-left:1px solid #e5e7eb}.notification-panel-header{padding:20px 24px;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:10;background:#fff}.notification-panel-header-left{display:flex;align-items:center;gap:12px}.notification-panel-title{margin:0;font-size:1.25rem;font-weight:600;color:#111827;letter-spacing:-.02em}.notification-panel-unread-count{background:#3b82f6;color:#fff;padding:2px 10px;border-radius:12px;font-size:.875rem;font-weight:600;min-width:24px;text-align:center}.notification-panel-close{background:transparent;border:none;padding:4px;cursor:pointer;color:#6b7280;display:flex;align-items:center;justify-content:center;border-radius:6px;transition:all .2s ease;width:32px;height:32px}.notification-panel-close:hover{background:#f3f4f6;color:#111827}.notification-panel-close cide-ele-icon{font-size:1.25rem!important}.notification-panel-body{flex:1;overflow-y:auto;padding:0}.notification-panel-body::-webkit-scrollbar{width:8px}.notification-panel-body::-webkit-scrollbar-track{background:#f9fafb}.notification-panel-body::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:4px}.notification-panel-body::-webkit-scrollbar-thumb:hover{background:#9ca3af}.notification-empty-state{padding:60px 24px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:4rem!important;color:#d1d5db!important;margin-bottom:16px}.notification-empty-text{margin:0;font-size:1rem;color:#6b7280;font-weight:500}.notification-panel-item{display:flex;align-items:flex-start;padding:16px 24px;cursor:pointer;transition:all .2s ease;position:relative;gap:16px;border-bottom:1px solid #f3f4f6}.notification-panel-item:hover{background:#f9fafb}.notification-panel-item.unread{background:#f8fafc}.notification-panel-item.unread:hover{background:#f1f5f9}.notification-avatar{flex-shrink:0;width:48px;height:48px;border-radius:50%;overflow:hidden;background:#e5e7eb;display:flex;align-items:center;justify-content:center}.notification-avatar-img{width:100%;height:100%;object-fit:cover}.notification-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;align-items:center;justify-content:center}.notification-avatar-placeholder cide-ele-icon{font-size:1.5rem!important;color:#fff!important}.notification-panel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}.notification-panel-text{font-size:.9375rem;color:#111827;line-height:1.5}.notification-panel-name{font-weight:600;color:#111827}.notification-panel-action{color:#4b5563;font-weight:400}.notification-panel-time{display:flex;gap:8px;align-items:center;font-size:.8125rem;color:#6b7280}.notification-time-full{font-weight:500}.notification-time-ago{color:#9ca3af}.notification-panel-message{margin-top:4px;font-size:.875rem;color:#4b5563;line-height:1.5}.notification-comment-bubble{margin-top:8px;padding:12px 16px;background:#f3f4f6;border-radius:12px;border-left:3px solid #3b82f6;font-size:.875rem;color:#374151;line-height:1.6;font-style:italic}.notification-file-preview{margin-top:8px;padding:12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;display:flex;align-items:center;gap:12px}.notification-file-icon{width:40px;height:40px;background:#e5e7eb;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:600;color:#6b7280;flex-shrink:0}.notification-file-info{flex:1;min-width:0}.notification-file-name{font-size:.875rem;font-weight:500;color:#111827;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.notification-file-size{font-size:.75rem;color:#6b7280}.notification-file-download{color:#6b7280;cursor:pointer;transition:color .2s ease;flex-shrink:0}.notification-file-download:hover{color:#3b82f6}.notification-actions-inline{margin-top:8px;display:flex;gap:8px}.notification-action-btn-inline{padding:6px 16px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.875rem;font-weight:500;cursor:pointer;transition:all .2s ease}.notification-action-btn-inline.decline{color:#6b7280}.notification-action-btn-inline.decline:hover{background:#f3f4f6;border-color:#d1d5db}.notification-action-btn-inline.accept{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn-inline.accept:hover{background:#2563eb;border-color:#2563eb}.notification-panel-unread-dot{position:absolute;top:20px;right:24px;width:10px;height:10px;border-radius:50%;background:#3b82f6;flex-shrink:0}\n"] }]
2396
+ CideEleDropdownComponent, CideEleFileImageDirective], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n #notificationDropdown\n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n [menuTemplate]=\"notificationMenuTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"tw-w-full tw-max-w-[380px] tw-min-w-[360px] tw-bg-white tw-rounded-none tw-shadow-[-2px_0_20px_rgba(0,0,0,0.1)] tw-overflow-hidden tw-flex tw-flex-col tw-max-h-[80vh] tw-border-l tw-border-l-gray-200\">\n <!-- Header -->\n <div class=\"tw-px-4 tw-py-3 tw-bg-white tw-border-b tw-border-b-gray-200 tw-flex tw-justify-between tw-items-center tw-sticky tw-top-0 tw-z-10\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <h3 class=\"tw-m-0 tw-text-base tw-font-semibold tw-text-gray-900\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"tw-bg-blue-500 tw-text-white tw-px-2 tw-py-0.5 tw-rounded-full tw-text-[11px] tw-font-semibold tw-min-w-5 tw-text-center tw-leading-none\">{{ unreadCount() }}</span>\n }\n </div>\n <button \n type=\"button\" \n class=\"tw-bg-transparent tw-border-none tw-p-1 tw-cursor-pointer tw-text-gray-500 tw-flex tw-items-center tw-justify-center tw-rounded tw-transition-all tw-duration-200 tw-w-7 tw-h-7 hover:tw-bg-gray-100 hover:tw-text-gray-900\"\n (click)=\"closeNotificationDropdown($event)\">\n <cide-ele-icon class=\"!tw-text-lg\">close</cide-ele-icon>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-p-0 [&::-webkit-scrollbar]:tw-w-1.5 [&::-webkit-scrollbar-track]:tw-bg-gray-50 [&::-webkit-scrollbar-thumb]:tw-bg-gray-300 [&::-webkit-scrollbar-thumb]:tw-rounded [&::-webkit-scrollbar-thumb]:hover:tw-bg-gray-400\">\n @if (notifications().length === 0) {\n <div class=\"tw-py-12 tw-px-4 tw-text-center tw-text-gray-400\">\n <cide-ele-icon class=\"!tw-text-5xl !tw-text-gray-300 tw-mb-3\">notifications_off</cide-ele-icon>\n <p class=\"tw-m-0 tw-text-sm tw-text-gray-500 tw-font-medium\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 15); track notif.id) {\n <div \n class=\"tw-flex tw-items-start tw-px-4 tw-py-3 tw-cursor-pointer tw-transition-all tw-duration-200 tw-relative tw-gap-2.5 tw-border-b tw-border-b-gray-100 hover:tw-bg-gray-50\"\n [class.tw-bg-white]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <!-- Profile Avatar -->\n <div class=\"tw-flex-shrink-0 tw-w-9 tw-h-9 tw-rounded-full tw-overflow-hidden tw-bg-gray-200 tw-flex tw-items-center tw-justify-center\">\n @if (getNotificationAvatar(notif)) {\n <img \n cideEleFileImage \n [fileId]=\"getNotificationAvatar(notif) || ''\"\n [altText]=\"getNotificationName(notif)\"\n class=\"tw-w-full tw-h-full tw-object-cover\">\n } @else {\n <div class=\"tw-w-full tw-h-full tw-bg-gradient-to-br tw-from-indigo-500 tw-to-purple-600 tw-text-white tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"!tw-text-lg !tw-text-white\">{{ getNotificationIcon(notif.type) }}</cide-ele-icon>\n </div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"tw-flex-1 tw-min-w-0 tw-flex tw-flex-col tw-gap-0.5 tw-pr-4\">\n <div class=\"tw-text-[13px] tw-text-gray-900 tw-leading-snug\">\n <span class=\"tw-font-semibold tw-text-gray-900\">{{ getNotificationName(notif) }}</span>\n <span class=\"tw-font-normal tw-text-gray-600 tw-ml-0.5\">{{ getNotificationAction(notif) }}</span>\n </div>\n <div class=\"tw-flex tw-gap-1.5 tw-items-center tw-text-[11px] tw-text-gray-500\">\n <span class=\"tw-font-medium tw-text-gray-500\">{{ getFullTime(notif.timestamp) }}</span>\n <span class=\"tw-text-gray-400 tw-font-normal\">\u2022</span>\n <span class=\"tw-text-gray-400 tw-font-normal\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n @if (notif.message && notif.message !== notif.title) {\n <div class=\"tw-mt-0.5 tw-text-[13px] tw-text-gray-600 tw-leading-snug\">\n {{ notif.message }}\n </div>\n }\n @if (notif.data?.comment) {\n <div class=\"tw-mt-1.5 tw-py-2 tw-px-3 tw-bg-gray-50 tw-rounded-md tw-border-l-3 tw-border-l-blue-500 tw-text-[12px] tw-text-gray-700 tw-leading-snug\">\n {{ notif.data.comment }}\n </div>\n }\n @if (notif.data?.file) {\n <div class=\"tw-mt-1.5 tw-py-2 tw-px-2.5 tw-bg-gray-50 tw-border tw-border-gray-200 tw-rounded-md tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-w-8 tw-h-8 tw-bg-gray-200 tw-rounded tw-flex tw-items-center tw-justify-center tw-text-[10px] tw-font-semibold tw-text-gray-500 tw-flex-shrink-0\">{{ getFileIcon(notif.data.file.type) }}</div>\n <div class=\"tw-flex-1 tw-min-w-0\">\n <div class=\"tw-text-[12px] tw-font-medium tw-text-gray-900 tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap\">{{ notif.data.file.name }}</div>\n <div class=\"tw-text-[10px] tw-text-gray-500\">{{ notif.data.file.size }}</div>\n </div>\n <cide-ele-icon class=\"tw-text-gray-500 tw-cursor-pointer tw-transition-colors tw-duration-200 tw-flex-shrink-0 tw-text-sm hover:tw-text-blue-500\">download</cide-ele-icon>\n </div>\n }\n @if (notif.action_label) {\n <div class=\"tw-mt-1.5 tw-flex tw-gap-2\">\n @if (notif.action_label.toLowerCase().includes('decline')) {\n <button type=\"button\" class=\"tw-py-1 tw-px-3 tw-border tw-border-gray-200 tw-bg-gray-50 tw-rounded-md tw-text-[12px] tw-font-medium tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-500 hover:tw-bg-gray-100 hover:tw-border-gray-300\">Decline</button>\n }\n @if (notif.action_label.toLowerCase().includes('accept')) {\n <button type=\"button\" class=\"tw-py-1 tw-px-3 tw-border tw-border-blue-500 tw-bg-blue-500 tw-rounded-md tw-text-[12px] tw-font-medium tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-white hover:tw-bg-blue-600 hover:tw-border-blue-600\">Accept</button>\n }\n </div>\n }\n </div>\n\n <!-- Unread Indicator -->\n @if (!isNotificationRead(notif)) {\n <div class=\"tw-absolute tw-top-3.5 tw-right-4 tw-w-2 tw-h-2 tw-rounded-full tw-bg-blue-500 tw-flex-shrink-0\"></div>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"] }]
2440
2397
  }], ctorParameters: () => [], propDecorators: { triggerTemplate: [{
2441
2398
  type: ViewChild,
2442
2399
  args: ['triggerTemplate']
@@ -3654,8 +3611,8 @@ class CideLytSidedrawerWrapperComponent {
3654
3611
  }
3655
3612
  ngOnInit() {
3656
3613
  // Initialize the component map (You'd likely populate this from a config or service)
3657
- this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-DnT1QLA7.mjs').then(m => m.CideLytSidedrawerNotesComponent);
3658
- this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-CuGm3ZnU.mjs').then(m => m.CideLytDrawerThemeComponent);
3614
+ this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-6ilViFo8.mjs').then(m => m.CideLytSidedrawerNotesComponent);
3615
+ this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-By_WtOQ-.mjs').then(m => m.CideLytDrawerThemeComponent);
3659
3616
  }
3660
3617
  async loadComponent(configFor) {
3661
3618
  console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
@@ -4178,7 +4135,7 @@ const layoutControlPannelChildRoutes = [{
4178
4135
  },
4179
4136
  {
4180
4137
  path: "home",
4181
- loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-BjZwFaSK.mjs').then(c => c.CideLytHomeWrapperComponent),
4138
+ loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-ZllC_HLn.mjs').then(c => c.CideLytHomeWrapperComponent),
4182
4139
  canActivate: [authGuard],
4183
4140
  data: {
4184
4141
  reuseTab: true, // For CustomRouteReuseStrategy
@@ -5746,4 +5703,4 @@ var floatingEntityRightsSharing_component = /*#__PURE__*/Object.freeze({
5746
5703
  */
5747
5704
 
5748
5705
  export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, AppStateService as e, CloudIdeLayoutService as f, CloudIdeLayoutComponent as g, CideLytSharedService as h, layoutControlPannelChildRoutes as i, CustomRouteReuseStrategy as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, CideLytFloatingEntityRightsSharingComponent as o, processThemeVariable as p, CideLytFloatingEntityRightsSharingService as q, setCSSVariable as s, themeFactory as t };
5749
- //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-B6GmMuGs.mjs.map
5706
+ //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-Dociv0e8.mjs.map