/** * Employees Controller * * Handles content swap between list view and detail view, * plus tab switching within each view. * Uses History API for browser back/forward navigation. */ export class EmployeesController { private listView: HTMLElement | null = null; private detailView: HTMLElement | null = null; constructor() { this.listView = document.getElementById('employees-list-view'); this.detailView = document.getElementById('employee-detail-view'); // Only initialize if we're on the employees page if (!this.listView) return; this.setupListTabs(); this.setupDetailTabs(); this.setupChevronNavigation(); this.setupBackNavigation(); this.setupHistoryNavigation(); this.restoreStateFromUrl(); } /** * Setup popstate listener for browser back/forward */ private setupHistoryNavigation(): void { window.addEventListener('popstate', (e: PopStateEvent) => { if (e.state?.employeeKey) { this.showDetailViewInternal(e.state.employeeKey); } else { this.showListViewInternal(); } }); } /** * Restore view state from URL on page load */ private restoreStateFromUrl(): void { const hash = window.location.hash; if (hash.startsWith('#employee-')) { const employeeKey = hash.substring(1); // Remove # this.showDetailViewInternal(employeeKey); } } /** * Setup tab switching for the list view */ private setupListTabs(): void { if (!this.listView) return; const tabs = this.listView.querySelectorAll('swp-tab-bar > swp-tab[data-tab]'); tabs.forEach(tab => { tab.addEventListener('click', () => { const targetTab = tab.dataset.tab; if (targetTab) { this.switchTab(this.listView!, targetTab); } }); }); } /** * Setup tab switching for the detail view */ private setupDetailTabs(): void { if (!this.detailView) return; const tabs = this.detailView.querySelectorAll('swp-tab-bar > swp-tab[data-tab]'); tabs.forEach(tab => { tab.addEventListener('click', () => { const targetTab = tab.dataset.tab; if (targetTab) { this.switchTab(this.detailView!, targetTab); } }); }); } /** * Switch to a specific tab within a container */ private switchTab(container: HTMLElement, targetTab: string): void { const tabs = container.querySelectorAll('swp-tab-bar > swp-tab[data-tab]'); const contents = container.querySelectorAll('swp-tab-content[data-tab]'); tabs.forEach(t => { t.classList.toggle('active', t.dataset.tab === targetTab); }); contents.forEach(content => { content.classList.toggle('active', content.dataset.tab === targetTab); }); } /** * Setup row click to show detail view * Ignores clicks on action buttons */ private setupChevronNavigation(): void { document.addEventListener('click', (e: Event) => { const target = e.target as HTMLElement; // Ignore clicks on action buttons if (target.closest('swp-icon-btn') || target.closest('swp-table-actions')) { return; } const row = target.closest('swp-employee-row[data-employee-detail]'); if (row) { const employeeKey = row.dataset.employeeDetail; if (employeeKey) { this.showDetailView(employeeKey); } } }); } /** * Setup back button to return to list view */ private setupBackNavigation(): void { document.addEventListener('click', (e: Event) => { const target = e.target as HTMLElement; const backLink = target.closest('[data-employee-back]'); if (backLink) { this.showListView(); } }); } /** * Show the detail view and hide list view (with history push) */ private showDetailView(employeeKey: string): void { // Push state to history history.pushState( { employeeKey }, '', `#${employeeKey}` ); this.showDetailViewInternal(employeeKey); } /** * Show detail view without modifying history (for popstate) */ private showDetailViewInternal(employeeKey: string): void { if (this.listView && this.detailView) { this.listView.style.display = 'none'; this.detailView.style.display = 'block'; this.detailView.dataset.employee = employeeKey; // Reset to first tab this.switchTab(this.detailView, 'general'); } } /** * Show the list view and hide detail view (with history push) */ private showListView(): void { // Push state to history (clear hash) history.pushState( {}, '', window.location.pathname ); this.showListViewInternal(); } /** * Show list view without modifying history (for popstate) */ private showListViewInternal(): void { if (this.listView && this.detailView) { this.detailView.style.display = 'none'; this.listView.style.display = 'block'; } } }