/** * Drawer Controller * * Handles all drawer functionality including profile, notifications, and todo drawers */ export type DrawerName = 'profile' | 'notification' | 'todo' | 'newTodo'; export class DrawerController { private profileDrawer: HTMLElement | null = null; private notificationDrawer: HTMLElement | null = null; private todoDrawer: HTMLElement | null = null; private newTodoDrawer: HTMLElement | null = null; private overlay: HTMLElement | null = null; private activeDrawer: DrawerName | null = null; constructor() { this.profileDrawer = document.getElementById('profileDrawer'); this.notificationDrawer = document.getElementById('notificationDrawer'); this.todoDrawer = document.getElementById('todoDrawer'); this.newTodoDrawer = document.getElementById('newTodoDrawer'); this.overlay = document.getElementById('drawerOverlay'); this.setupListeners(); } /** * Get currently active drawer name */ get active(): DrawerName | null { return this.activeDrawer; } /** * Open a drawer by name */ open(name: DrawerName): void { this.closeAll(); const drawer = this.getDrawer(name); if (drawer && this.overlay) { drawer.classList.add('active'); this.overlay.classList.add('active'); document.body.style.overflow = 'hidden'; this.activeDrawer = name; } } /** * Close a specific drawer */ close(name: DrawerName): void { const drawer = this.getDrawer(name); drawer?.classList.remove('active'); // Only hide overlay if no drawers are active if (this.overlay && !document.querySelector('.active[class*="drawer"]')) { this.overlay.classList.remove('active'); document.body.style.overflow = ''; } if (this.activeDrawer === name) { this.activeDrawer = null; } } /** * Close all drawers */ closeAll(): void { [this.profileDrawer, this.notificationDrawer, this.todoDrawer, this.newTodoDrawer] .forEach(drawer => drawer?.classList.remove('active')); this.overlay?.classList.remove('active'); document.body.style.overflow = ''; this.activeDrawer = null; } /** * Open profile drawer */ openProfile(): void { this.open('profile'); } /** * Open notification drawer */ openNotification(): void { this.open('notification'); } /** * Open todo drawer (slides on top of profile) */ openTodo(): void { this.todoDrawer?.classList.add('active'); } /** * Close todo drawer */ closeTodo(): void { this.todoDrawer?.classList.remove('active'); this.closeNewTodo(); } /** * Open new todo drawer */ openNewTodo(): void { this.newTodoDrawer?.classList.add('active'); } /** * Close new todo drawer */ closeNewTodo(): void { this.newTodoDrawer?.classList.remove('active'); } /** * Mark all notifications as read */ markAllNotificationsRead(): void { if (!this.notificationDrawer) return; const unreadItems = this.notificationDrawer.querySelectorAll( 'swp-notification-item[data-unread="true"]' ); unreadItems.forEach(item => item.removeAttribute('data-unread')); const badge = document.querySelector('swp-notification-badge'); if (badge) { badge.style.display = 'none'; } } private getDrawer(name: DrawerName): HTMLElement | null { switch (name) { case 'profile': return this.profileDrawer; case 'notification': return this.notificationDrawer; case 'todo': return this.todoDrawer; case 'newTodo': return this.newTodoDrawer; } } private setupListeners(): void { // Profile drawer triggers document.getElementById('profileTrigger') ?.addEventListener('click', () => this.openProfile()); document.getElementById('drawerClose') ?.addEventListener('click', () => this.close('profile')); // Notification drawer triggers document.getElementById('notificationsBtn') ?.addEventListener('click', () => this.openNotification()); document.getElementById('notificationDrawerClose') ?.addEventListener('click', () => this.close('notification')); document.getElementById('markAllRead') ?.addEventListener('click', () => this.markAllNotificationsRead()); // Todo drawer triggers document.getElementById('openTodoDrawer') ?.addEventListener('click', () => this.openTodo()); document.getElementById('todoDrawerBack') ?.addEventListener('click', () => this.closeTodo()); // New todo drawer triggers document.getElementById('addTodoBtn') ?.addEventListener('click', () => this.openNewTodo()); document.getElementById('newTodoDrawerBack') ?.addEventListener('click', () => this.closeNewTodo()); document.getElementById('cancelNewTodo') ?.addEventListener('click', () => this.closeNewTodo()); document.getElementById('saveNewTodo') ?.addEventListener('click', () => this.closeNewTodo()); // Overlay click closes all this.overlay?.addEventListener('click', () => this.closeAll()); // Escape key closes all document.addEventListener('keydown', (e: KeyboardEvent) => { if (e.key === 'Escape') this.closeAll(); }); // Todo interactions this.todoDrawer?.addEventListener('click', (e) => this.handleTodoClick(e)); // Visibility options document.addEventListener('click', (e) => this.handleVisibilityClick(e)); } private handleTodoClick(e: Event): void { const target = e.target as HTMLElement; const todoItem = target.closest('swp-todo-item'); const checkbox = target.closest('swp-todo-checkbox'); if (checkbox && todoItem) { const isCompleted = todoItem.dataset.completed === 'true'; if (isCompleted) { todoItem.removeAttribute('data-completed'); } else { todoItem.dataset.completed = 'true'; } } // Toggle section collapse const sectionHeader = target.closest('swp-todo-section-header'); if (sectionHeader) { const section = sectionHeader.closest('swp-todo-section'); section?.classList.toggle('collapsed'); } } private handleVisibilityClick(e: Event): void { const target = e.target as HTMLElement; const option = target.closest('swp-visibility-option'); if (option) { document.querySelectorAll('swp-visibility-option') .forEach(o => o.classList.remove('active')); option.classList.add('active'); } } }