cloud-ide-layout 1.0.64 → 1.0.66

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-8S-2Ir2T.mjs → cloud-ide-layout-cloud-ide-layout-CSze0AFt.mjs} +142 -96
  2. package/fesm2022/cloud-ide-layout-cloud-ide-layout-CSze0AFt.mjs.map +1 -0
  3. package/fesm2022/{cloud-ide-layout-drawer-theme.component-j59G67L1.mjs → cloud-ide-layout-drawer-theme.component-BAjiidNV.mjs} +2 -2
  4. package/fesm2022/{cloud-ide-layout-drawer-theme.component-j59G67L1.mjs.map → cloud-ide-layout-drawer-theme.component-BAjiidNV.mjs.map} +1 -1
  5. package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Bv5s966h.mjs → cloud-ide-layout-floating-entity-selection.component-IE3wkDmZ.mjs} +2 -2
  6. package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Bv5s966h.mjs.map → cloud-ide-layout-floating-entity-selection.component-IE3wkDmZ.mjs.map} +1 -1
  7. package/fesm2022/{cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs → cloud-ide-layout-home-wrapper.component-B2nYKw-W.mjs} +2 -2
  8. package/fesm2022/{cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs.map → cloud-ide-layout-home-wrapper.component-B2nYKw-W.mjs.map} +1 -1
  9. package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.mjs → cloud-ide-layout-sidedrawer-notes.component-CC-oA1YF.mjs} +2 -2
  10. package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.mjs.map → cloud-ide-layout-sidedrawer-notes.component-CC-oA1YF.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-8S-2Ir2T.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-Bv5s966h.mjs');
1269
+ const module = await import('./cloud-ide-layout-floating-entity-selection.component-IE3wkDmZ.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');
@@ -1350,6 +1350,7 @@ class CideLytHeaderWrapperComponent {
1350
1350
  financialYearTriggerTemplate;
1351
1351
  academicYearTriggerTemplate;
1352
1352
  notificationTriggerTemplate;
1353
+ notificationDropdown; // Dropdown component reference
1353
1354
  // Inject app state service to get active entity
1354
1355
  appStateService = inject(AppStateService);
1355
1356
  // Inject floating entity selection service
@@ -1552,20 +1553,21 @@ class CideLytHeaderWrapperComponent {
1552
1553
  }
1553
1554
  /**
1554
1555
  * Load notifications from API
1555
- * @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.
1556
1557
  */
1557
- loadNotifications(showReadOnly = false) {
1558
+ loadNotifications(showAll = false) {
1558
1559
  try {
1559
1560
  // Get notifications from WebSocket service (real-time)
1560
1561
  const wsNotifications = this.wsNotificationService?.allNotifications() || [];
1561
1562
  console.log('[Notifications] WebSocket notifications:', wsNotifications.length);
1562
1563
  // Load from API to get all notifications (including read status)
1563
- // By default, we can filter to show unread first, but load all for "View All"
1564
1564
  const params = {
1565
- pageSize: 20
1565
+ pageSize: showAll ? 100 : 20
1566
1566
  };
1567
- // Optionally filter by status if we only want unread
1568
- // 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
+ }
1569
1571
  this.notificationApiService.getNotifications(params).subscribe({
1570
1572
  next: (response) => {
1571
1573
  console.log('[Notifications] API response:', response);
@@ -1587,6 +1589,11 @@ class CideLytHeaderWrapperComponent {
1587
1589
  isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
1588
1590
  }));
1589
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
+ });
1590
1597
  // Merge WebSocket and API notifications (API takes priority for read status)
1591
1598
  const mergedNotifications = [];
1592
1599
  // Add API notifications first (they have read status)
@@ -1599,29 +1606,31 @@ class CideLytHeaderWrapperComponent {
1599
1606
  mergedNotifications.push({ ...wsNotif, isRead: false });
1600
1607
  }
1601
1608
  });
1602
- // Sort by timestamp (newest first)
1603
- mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
1604
- console.log('[Notifications] Total merged notifications:', mergedNotifications.length);
1605
- // Update WebSocket service with read status
1606
- if (this.wsNotificationService) {
1607
- // Update unread count based on read status
1608
- const unread = mergedNotifications.filter(n => !n.isRead);
1609
- // 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);
1610
1614
  }
1611
- 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);
1612
1619
  this.updateNotificationDropdown();
1613
1620
  }
1614
1621
  else {
1615
1622
  console.warn('[Notifications] API response invalid, using WebSocket notifications only');
1616
- // Fallback to WebSocket notifications only
1617
- 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);
1618
1626
  this.updateNotificationDropdown();
1619
1627
  }
1620
1628
  },
1621
1629
  error: (error) => {
1622
1630
  console.error('[Notifications] Error loading from API:', error);
1623
- // Fallback to WebSocket notifications only
1624
- 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);
1625
1634
  this.updateNotificationDropdown();
1626
1635
  }
1627
1636
  });
@@ -1755,13 +1764,98 @@ class CideLytHeaderWrapperComponent {
1755
1764
  const hours = Math.floor(minutes / 60);
1756
1765
  const days = Math.floor(hours / 24);
1757
1766
  if (days > 0)
1758
- return `${days}d ago`;
1767
+ return `${days} ${days === 1 ? 'day' : 'days'} ago`;
1759
1768
  if (hours > 0)
1760
- return `${hours}h ago`;
1769
+ return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;
1761
1770
  if (minutes > 0)
1762
- return `${minutes}m ago`;
1771
+ return `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago`;
1763
1772
  return 'Just now';
1764
1773
  }
1774
+ /**
1775
+ * Get full time string (e.g., "Friday 3:12 PM")
1776
+ */
1777
+ getFullTime(timestamp) {
1778
+ const date = new Date(timestamp);
1779
+ const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
1780
+ const dayName = days[date.getDay()];
1781
+ const hours = date.getHours();
1782
+ const minutes = date.getMinutes();
1783
+ const ampm = hours >= 12 ? 'PM' : 'AM';
1784
+ const displayHours = hours % 12 || 12;
1785
+ const displayMinutes = minutes.toString().padStart(2, '0');
1786
+ return `${dayName} ${displayHours}:${displayMinutes} ${ampm}`;
1787
+ }
1788
+ /**
1789
+ * Get notification name (from data or title)
1790
+ */
1791
+ getNotificationName(notification) {
1792
+ if (notification.data?.user_name)
1793
+ return notification.data.user_name;
1794
+ if (notification.data?.name)
1795
+ return notification.data.name;
1796
+ // Extract name from title if format is "Name action..."
1797
+ const titleParts = notification.title.split(' ');
1798
+ if (titleParts.length > 1) {
1799
+ return titleParts[0];
1800
+ }
1801
+ return 'System';
1802
+ }
1803
+ /**
1804
+ * Get notification action text
1805
+ */
1806
+ getNotificationAction(notification) {
1807
+ const title = notification.title;
1808
+ const name = this.getNotificationName(notification);
1809
+ // Remove the name from title to get action
1810
+ return title.replace(name, '').trim();
1811
+ }
1812
+ /**
1813
+ * Get notification avatar (from data or created_by)
1814
+ */
1815
+ getNotificationAvatar(notification) {
1816
+ if (notification.data?.user_photo_id_cyfm)
1817
+ return notification.data.user_photo_id_cyfm;
1818
+ if (notification.data?.photo_id)
1819
+ return notification.data.photo_id;
1820
+ // Try to get from created_by if it's a populated object
1821
+ const createdBy = notification.not_id_created_by;
1822
+ if (createdBy && typeof createdBy === 'object' && createdBy.user_photo_id_cyfm) {
1823
+ return createdBy.user_photo_id_cyfm;
1824
+ }
1825
+ return null;
1826
+ }
1827
+ /**
1828
+ * Get file icon based on file type
1829
+ */
1830
+ getFileIcon(fileType) {
1831
+ if (!fileType)
1832
+ return 'description';
1833
+ const type = fileType.toLowerCase();
1834
+ if (type.includes('pdf'))
1835
+ return 'PDF';
1836
+ if (type.includes('mp4') || type.includes('video'))
1837
+ return 'MP4';
1838
+ if (type.includes('image'))
1839
+ return 'IMG';
1840
+ if (type.includes('word') || type.includes('doc'))
1841
+ return 'DOC';
1842
+ if (type.includes('excel') || type.includes('xls'))
1843
+ return 'XLS';
1844
+ return 'FILE';
1845
+ }
1846
+ /**
1847
+ * Close notification dropdown
1848
+ */
1849
+ closeNotificationDropdown(event) {
1850
+ event.stopPropagation();
1851
+ // Close the dropdown by toggling it if it's open
1852
+ if (this.notificationDropdown && typeof this.notificationDropdown.toggleDropdown === 'function') {
1853
+ // If dropdown is open, toggle to close it
1854
+ if (this.notificationDropdown.isOpen && this.notificationDropdown.isOpen()) {
1855
+ this.notificationDropdown.toggleDropdown(event);
1856
+ }
1857
+ }
1858
+ }
1765
1859
  /**
1766
1860
  * Get notification icon color class
1767
1861
  */
@@ -1818,8 +1912,8 @@ class CideLytHeaderWrapperComponent {
1818
1912
  this.notificationApiService.markAsRead(notificationId).subscribe({
1819
1913
  next: (response) => {
1820
1914
  console.log('[Notifications] Marked as read successfully:', response);
1821
- // Reload notifications to update unread count
1822
- this.loadNotifications();
1915
+ // Reload notifications to update unread count (only show unread)
1916
+ this.loadNotifications(false); // false = only show unread
1823
1917
  },
1824
1918
  error: (error) => {
1825
1919
  console.error('[Notifications] Error marking notification as read:', error);
@@ -1842,8 +1936,14 @@ class CideLytHeaderWrapperComponent {
1842
1936
  this.notificationApiService.markAllAsRead().subscribe({
1843
1937
  next: (response) => {
1844
1938
  console.log('[Notifications] All notifications marked as read successfully:', response);
1845
- // Reload notifications to update unread count
1846
- 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);
1847
1947
  },
1848
1948
  error: (error) => {
1849
1949
  console.error('[Notifications] Error marking all as read:', error);
@@ -1854,7 +1954,7 @@ class CideLytHeaderWrapperComponent {
1854
1954
  url: error?.url
1855
1955
  });
1856
1956
  // Still reload to get updated state
1857
- this.loadNotifications();
1957
+ this.loadNotifications(false); // false = only show unread
1858
1958
  }
1859
1959
  });
1860
1960
  }
@@ -1868,19 +1968,13 @@ class CideLytHeaderWrapperComponent {
1868
1968
  this.notificationApiService.markAllAsRead().subscribe({
1869
1969
  next: (response) => {
1870
1970
  console.log('[Notifications] All notifications marked as read:', response);
1871
- // Filter current notifications to mark them as read locally
1872
- const currentNotifs = this.notifications();
1873
- const updatedNotifs = currentNotifs.map(notif => ({
1874
- ...notif,
1875
- isRead: true
1876
- }));
1877
- // Clear notifications from view (they're all read now)
1971
+ // Clear notifications from view immediately (they're all read now)
1878
1972
  this.notifications.set([]);
1879
1973
  this.updateNotificationDropdown();
1880
1974
  // Reload after a short delay to get updated state from server
1881
1975
  // This will show empty or only new unread notifications
1882
1976
  setTimeout(() => {
1883
- this.loadNotifications();
1977
+ this.loadNotifications(false); // false = only show unread
1884
1978
  }, 500);
1885
1979
  },
1886
1980
  error: (error) => {
@@ -1892,7 +1986,7 @@ class CideLytHeaderWrapperComponent {
1892
1986
  url: error?.url
1893
1987
  });
1894
1988
  // Still try to reload
1895
- this.loadNotifications();
1989
+ this.loadNotifications(false); // false = only show unread
1896
1990
  }
1897
1991
  });
1898
1992
  }
@@ -1902,60 +1996,9 @@ class CideLytHeaderWrapperComponent {
1902
1996
  */
1903
1997
  loadAllNotifications() {
1904
1998
  try {
1905
- const wsNotifications = this.wsNotificationService?.allNotifications() || [];
1906
1999
  console.log('[Notifications] Loading all notifications (View All)');
1907
- // Load more notifications from API (increase pageSize)
1908
- this.notificationApiService.getNotifications({
1909
- pageSize: 100 // Load more for "View All"
1910
- }).subscribe({
1911
- next: (response) => {
1912
- console.log('[Notifications] All notifications API response:', response);
1913
- if (response && response.success && response.data) {
1914
- // Convert server notifications to notification payloads
1915
- const apiPayloads = response.data.map((notif) => ({
1916
- id: String(notif._id),
1917
- type: notif.not_type || 'info',
1918
- category: notif.not_category,
1919
- title: notif.not_title,
1920
- message: notif.not_message,
1921
- data: notif.not_data,
1922
- action_url: notif.not_action_url,
1923
- action_label: notif.not_action_label,
1924
- priority: notif.not_priority || 'normal',
1925
- created_at: new Date(notif.not_created_at),
1926
- timestamp: new Date(notif.not_created_at),
1927
- isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
1928
- }));
1929
- // Merge WebSocket and API notifications
1930
- const mergedNotifications = [];
1931
- // Add API notifications first
1932
- apiPayloads.forEach(apiNotif => {
1933
- mergedNotifications.push(apiNotif);
1934
- });
1935
- // Add WebSocket notifications that aren't in API
1936
- wsNotifications.forEach(wsNotif => {
1937
- if (!mergedNotifications.find(n => n.id === wsNotif.id)) {
1938
- mergedNotifications.push({ ...wsNotif, isRead: false });
1939
- }
1940
- });
1941
- // Sort by timestamp (newest first)
1942
- mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
1943
- console.log('[Notifications] Total notifications loaded:', mergedNotifications.length);
1944
- this.notifications.set(mergedNotifications);
1945
- this.updateNotificationDropdown();
1946
- }
1947
- else {
1948
- console.warn('[Notifications] API response invalid');
1949
- this.notifications.set(wsNotifications);
1950
- this.updateNotificationDropdown();
1951
- }
1952
- },
1953
- error: (error) => {
1954
- console.error('[Notifications] Error loading all notifications:', error);
1955
- this.notifications.set(wsNotifications);
1956
- this.updateNotificationDropdown();
1957
- }
1958
- });
2000
+ // Load all notifications (read + unread) for "View All"
2001
+ this.loadNotifications(true); // true = show all (read + unread)
1959
2002
  }
1960
2003
  catch (error) {
1961
2004
  console.error('[Notifications] Error in loadAllNotifications:', error);
@@ -2345,12 +2388,12 @@ class CideLytHeaderWrapperComponent {
2345
2388
  }
2346
2389
  }
2347
2390
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2348
- 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 }], 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 [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-dropdown-menu\">\n <!-- Header -->\n <div class=\"notification-dropdown-header\">\n <h3 class=\"notification-dropdown-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-unread-badge\">{{ unreadCount() }} unread</span>\n }\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-dropdown-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, 10); track notif.id) {\n <div \n class=\"notification-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <div class=\"notification-item-icon\">\n <cide-ele-icon [class]=\"getNotificationIconColorClass(notif.type)\">\n {{ getNotificationIcon(notif.type) }}\n </cide-ele-icon>\n </div>\n <div class=\"notification-item-content\">\n <div class=\"notification-item-header\">\n <h4 class=\"notification-item-title\">{{ notif.title }}</h4>\n <span class=\"notification-item-time\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n <p class=\"notification-item-message\">{{ notif.message }}</p>\n @if (notif.priority === 'urgent') {\n <span class=\"notification-priority-badge urgent\">Urgent</span>\n }\n </div>\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-unread-indicator\"></div>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer Actions -->\n @if (notifications().length > 0) {\n <div class=\"notification-dropdown-footer\">\n <div class=\"notification-actions\">\n @if (unreadCount() > 0) {\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"markAllAsRead()\">\n <cide-ele-icon>done_all</cide-ele-icon>\n <span>Mark all read</span>\n </button>\n }\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"clearAllNotifications()\">\n <cide-ele-icon>clear_all</cide-ele-icon>\n <span>Clear all</span>\n </button>\n <button \n type=\"button\" \n class=\"notification-action-btn primary\"\n (click)=\"loadAllNotifications()\">\n <cide-ele-icon>list</cide-ele-icon>\n <span>View all</span>\n </button>\n </div>\n </div>\n }\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-dropdown-menu{width:100%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;overflow:hidden;display:flex;flex-direction:column;max-height:600px}.notification-dropdown-header{padding:16px 20px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(255,255,255,.1)}.notification-dropdown-title{margin:0;font-size:1.1rem;font-weight:600;letter-spacing:-.01em}.notification-unread-badge{background:#ffffff40;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;border:1px solid rgba(255,255,255,.3)}.notification-dropdown-body{flex:1;overflow-y:auto;max-height:450px;padding:8px 0}.notification-dropdown-body::-webkit-scrollbar{width:6px}.notification-dropdown-body::-webkit-scrollbar-track{background:#f1f1f1}.notification-dropdown-body::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.notification-dropdown-body::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.notification-empty-state{padding:40px 20px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:3rem!important;color:#d1d5db!important;margin-bottom:12px}.notification-empty-text{margin:0;font-size:.9rem;color:#6b7280}.notification-item{display:flex;align-items:flex-start;padding:12px 20px;cursor:pointer;transition:all .2s ease;border-left:3px solid transparent;position:relative;gap:12px}.notification-item:hover{background:#f9fafb;border-left-color:#3b82f6}.notification-item.unread{background:#eff6ff;border-left-color:#3b82f6}.notification-item.unread:hover{background:#dbeafe}.notification-item-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:#f3f4f6;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.notification-item.unread .notification-item-icon{background:#dbeafe}.notification-item-icon cide-ele-icon{font-size:1.25rem!important}.notification-item-content{flex:1;min-width:0}.notification-item-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:4px}.notification-item-title{margin:0;font-size:.9rem;font-weight:600;color:#111827;line-height:1.4;flex:1}.notification-item-time{font-size:.75rem;color:#6b7280;white-space:nowrap;flex-shrink:0}.notification-item-message{margin:0;font-size:.85rem;color:#4b5563;line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.notification-priority-badge{display:inline-block;margin-top:6px;padding:2px 8px;border-radius:4px;font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.notification-priority-badge.urgent{background:#fee2e2;color:#dc2626}.notification-unread-indicator{position:absolute;top:16px;right:16px;width:8px;height:8px;border-radius:50%;background:#3b82f6;box-shadow:0 0 0 2px #fff}.notification-dropdown-footer{padding:12px 20px;background:#f9fafb;border-top:1px solid #e5e7eb}.notification-actions{display:flex;gap:8px;justify-content:flex-end}.notification-action-btn{display:flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8rem;color:#4b5563;cursor:pointer;transition:all .2s ease;font-weight:500}.notification-action-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.notification-action-btn.primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn.primary:hover{background:#2563eb;border-color:#2563eb}.notification-action-btn cide-ele-icon{font-size:1rem!important}\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=\"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-separator\">\u2022</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;min-width:380px;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;background:#fff;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:10}.notification-panel-header-left{display:flex;align-items:center;gap:12px}.notification-panel-title{margin:0;font-size:1.125rem;font-weight:600;color:#111827;letter-spacing:-.01em}.notification-panel-unread-count{background:#3b82f6;color:#fff;padding:4px 10px;border-radius:12px;font-size:.8125rem;font-weight:600;min-width:24px;text-align:center;line-height:1}.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 20px;cursor:pointer;transition:all .2s ease;position:relative;gap:12px;border-bottom:1px solid #f3f4f6}.notification-panel-item:hover{background:#f9fafb}.notification-panel-item.unread{background:#fff}.notification-panel-item.unread:hover{background:#f9fafb}.notification-avatar{flex-shrink:0;width:40px;height:40px;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.25rem!important;color:#fff!important}.notification-panel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;padding-right:24px}.notification-panel-text{font-size:.875rem;color:#111827;line-height:1.5;margin-bottom:2px}.notification-panel-name{font-weight:600;color:#111827}.notification-panel-action{color:#4b5563;font-weight:400}.notification-panel-time{display:flex;gap:6px;align-items:center;font-size:.75rem;color:#6b7280;margin-top:2px}.notification-time-full{font-weight:500;color:#6b7280}.notification-time-separator,.notification-time-ago{color:#9ca3af;font-weight:400}.notification-panel-message{margin-top:4px;font-size:.875rem;color:#4b5563;line-height:1.5}.notification-comment-bubble{margin-top:8px;padding:10px 14px;background:#f9fafb;border-radius:8px;border-left:3px solid #3b82f6;font-size:.8125rem;color:#374151;line-height:1.5;font-style:normal}.notification-file-preview{margin-top:8px;padding:10px 12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;display:flex;align-items:center;gap:10px}.notification-file-icon{width:36px;height:36px;background:#e5e7eb;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;color:#6b7280;flex-shrink:0}.notification-file-info{flex:1;min-width:0}.notification-file-name{font-size:.8125rem;font-weight:500;color:#111827;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.notification-file-size{font-size:.6875rem;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 14px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8125rem;font-weight:500;cursor:pointer;transition:all .2s ease}.notification-action-btn-inline.decline{color:#6b7280;background:#f9fafb}.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:20px;width:8px;height:8px;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"] }] });
2349
2392
  }
2350
2393
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
2351
2394
  type: Component,
2352
2395
  args: [{ selector: 'cide-lyt-header-wrapper', imports: [CideInputComponent, CommonModule, CideIconComponent,
2353
- 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 [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-dropdown-menu\">\n <!-- Header -->\n <div class=\"notification-dropdown-header\">\n <h3 class=\"notification-dropdown-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-unread-badge\">{{ unreadCount() }} unread</span>\n }\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-dropdown-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, 10); track notif.id) {\n <div \n class=\"notification-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <div class=\"notification-item-icon\">\n <cide-ele-icon [class]=\"getNotificationIconColorClass(notif.type)\">\n {{ getNotificationIcon(notif.type) }}\n </cide-ele-icon>\n </div>\n <div class=\"notification-item-content\">\n <div class=\"notification-item-header\">\n <h4 class=\"notification-item-title\">{{ notif.title }}</h4>\n <span class=\"notification-item-time\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n <p class=\"notification-item-message\">{{ notif.message }}</p>\n @if (notif.priority === 'urgent') {\n <span class=\"notification-priority-badge urgent\">Urgent</span>\n }\n </div>\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-unread-indicator\"></div>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer Actions -->\n @if (notifications().length > 0) {\n <div class=\"notification-dropdown-footer\">\n <div class=\"notification-actions\">\n @if (unreadCount() > 0) {\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"markAllAsRead()\">\n <cide-ele-icon>done_all</cide-ele-icon>\n <span>Mark all read</span>\n </button>\n }\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"clearAllNotifications()\">\n <cide-ele-icon>clear_all</cide-ele-icon>\n <span>Clear all</span>\n </button>\n <button \n type=\"button\" \n class=\"notification-action-btn primary\"\n (click)=\"loadAllNotifications()\">\n <cide-ele-icon>list</cide-ele-icon>\n <span>View all</span>\n </button>\n </div>\n </div>\n }\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-dropdown-menu{width:100%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;overflow:hidden;display:flex;flex-direction:column;max-height:600px}.notification-dropdown-header{padding:16px 20px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(255,255,255,.1)}.notification-dropdown-title{margin:0;font-size:1.1rem;font-weight:600;letter-spacing:-.01em}.notification-unread-badge{background:#ffffff40;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;border:1px solid rgba(255,255,255,.3)}.notification-dropdown-body{flex:1;overflow-y:auto;max-height:450px;padding:8px 0}.notification-dropdown-body::-webkit-scrollbar{width:6px}.notification-dropdown-body::-webkit-scrollbar-track{background:#f1f1f1}.notification-dropdown-body::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.notification-dropdown-body::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.notification-empty-state{padding:40px 20px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:3rem!important;color:#d1d5db!important;margin-bottom:12px}.notification-empty-text{margin:0;font-size:.9rem;color:#6b7280}.notification-item{display:flex;align-items:flex-start;padding:12px 20px;cursor:pointer;transition:all .2s ease;border-left:3px solid transparent;position:relative;gap:12px}.notification-item:hover{background:#f9fafb;border-left-color:#3b82f6}.notification-item.unread{background:#eff6ff;border-left-color:#3b82f6}.notification-item.unread:hover{background:#dbeafe}.notification-item-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:#f3f4f6;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.notification-item.unread .notification-item-icon{background:#dbeafe}.notification-item-icon cide-ele-icon{font-size:1.25rem!important}.notification-item-content{flex:1;min-width:0}.notification-item-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:4px}.notification-item-title{margin:0;font-size:.9rem;font-weight:600;color:#111827;line-height:1.4;flex:1}.notification-item-time{font-size:.75rem;color:#6b7280;white-space:nowrap;flex-shrink:0}.notification-item-message{margin:0;font-size:.85rem;color:#4b5563;line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.notification-priority-badge{display:inline-block;margin-top:6px;padding:2px 8px;border-radius:4px;font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.notification-priority-badge.urgent{background:#fee2e2;color:#dc2626}.notification-unread-indicator{position:absolute;top:16px;right:16px;width:8px;height:8px;border-radius:50%;background:#3b82f6;box-shadow:0 0 0 2px #fff}.notification-dropdown-footer{padding:12px 20px;background:#f9fafb;border-top:1px solid #e5e7eb}.notification-actions{display:flex;gap:8px;justify-content:flex-end}.notification-action-btn{display:flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8rem;color:#4b5563;cursor:pointer;transition:all .2s ease;font-weight:500}.notification-action-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.notification-action-btn.primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn.primary:hover{background:#2563eb;border-color:#2563eb}.notification-action-btn cide-ele-icon{font-size:1rem!important}\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=\"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-separator\">\u2022</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;min-width:380px;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;background:#fff;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:10}.notification-panel-header-left{display:flex;align-items:center;gap:12px}.notification-panel-title{margin:0;font-size:1.125rem;font-weight:600;color:#111827;letter-spacing:-.01em}.notification-panel-unread-count{background:#3b82f6;color:#fff;padding:4px 10px;border-radius:12px;font-size:.8125rem;font-weight:600;min-width:24px;text-align:center;line-height:1}.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 20px;cursor:pointer;transition:all .2s ease;position:relative;gap:12px;border-bottom:1px solid #f3f4f6}.notification-panel-item:hover{background:#f9fafb}.notification-panel-item.unread{background:#fff}.notification-panel-item.unread:hover{background:#f9fafb}.notification-avatar{flex-shrink:0;width:40px;height:40px;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.25rem!important;color:#fff!important}.notification-panel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;padding-right:24px}.notification-panel-text{font-size:.875rem;color:#111827;line-height:1.5;margin-bottom:2px}.notification-panel-name{font-weight:600;color:#111827}.notification-panel-action{color:#4b5563;font-weight:400}.notification-panel-time{display:flex;gap:6px;align-items:center;font-size:.75rem;color:#6b7280;margin-top:2px}.notification-time-full{font-weight:500;color:#6b7280}.notification-time-separator,.notification-time-ago{color:#9ca3af;font-weight:400}.notification-panel-message{margin-top:4px;font-size:.875rem;color:#4b5563;line-height:1.5}.notification-comment-bubble{margin-top:8px;padding:10px 14px;background:#f9fafb;border-radius:8px;border-left:3px solid #3b82f6;font-size:.8125rem;color:#374151;line-height:1.5;font-style:normal}.notification-file-preview{margin-top:8px;padding:10px 12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;display:flex;align-items:center;gap:10px}.notification-file-icon{width:36px;height:36px;background:#e5e7eb;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:600;color:#6b7280;flex-shrink:0}.notification-file-info{flex:1;min-width:0}.notification-file-name{font-size:.8125rem;font-weight:500;color:#111827;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.notification-file-size{font-size:.6875rem;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 14px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8125rem;font-weight:500;cursor:pointer;transition:all .2s ease}.notification-action-btn-inline.decline{color:#6b7280;background:#f9fafb}.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:20px;width:8px;height:8px;border-radius:50%;background:#3b82f6;flex-shrink:0}\n"] }]
2354
2397
  }], ctorParameters: () => [], propDecorators: { triggerTemplate: [{
2355
2398
  type: ViewChild,
2356
2399
  args: ['triggerTemplate']
@@ -2363,6 +2406,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
2363
2406
  }], notificationTriggerTemplate: [{
2364
2407
  type: ViewChild,
2365
2408
  args: ['notificationTriggerTemplate']
2409
+ }], notificationDropdown: [{
2410
+ type: ViewChild,
2411
+ args: ['notificationDropdown']
2366
2412
  }] } });
2367
2413
 
2368
2414
  class CideLytUserStatusService {
@@ -3565,8 +3611,8 @@ class CideLytSidedrawerWrapperComponent {
3565
3611
  }
3566
3612
  ngOnInit() {
3567
3613
  // Initialize the component map (You'd likely populate this from a config or service)
3568
- this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.mjs').then(m => m.CideLytSidedrawerNotesComponent);
3569
- this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-j59G67L1.mjs').then(m => m.CideLytDrawerThemeComponent);
3614
+ this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-CC-oA1YF.mjs').then(m => m.CideLytSidedrawerNotesComponent);
3615
+ this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-BAjiidNV.mjs').then(m => m.CideLytDrawerThemeComponent);
3570
3616
  }
3571
3617
  async loadComponent(configFor) {
3572
3618
  console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
@@ -4089,7 +4135,7 @@ const layoutControlPannelChildRoutes = [{
4089
4135
  },
4090
4136
  {
4091
4137
  path: "home",
4092
- loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs').then(c => c.CideLytHomeWrapperComponent),
4138
+ loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-B2nYKw-W.mjs').then(c => c.CideLytHomeWrapperComponent),
4093
4139
  canActivate: [authGuard],
4094
4140
  data: {
4095
4141
  reuseTab: true, // For CustomRouteReuseStrategy
@@ -5657,4 +5703,4 @@ var floatingEntityRightsSharing_component = /*#__PURE__*/Object.freeze({
5657
5703
  */
5658
5704
 
5659
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 };
5660
- //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-8S-2Ir2T.mjs.map
5706
+ //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-CSze0AFt.mjs.map