|
32 | 32 |
|
33 | 33 | let isDark = $state(false); |
34 | 34 | let userDropdownOpen = $state(false); |
| 35 | + let dropdownRef = $state(); |
35 | 36 |
|
36 | 37 | const closeDrawer = () => { |
37 | 38 | drawerHidden = true; |
|
46 | 47 | userDropdownOpen = !userDropdownOpen; |
47 | 48 | }; |
48 | 49 |
|
| 50 | + const handleSettingsLinkClick = (event, href) => { |
| 51 | + event.preventDefault(); |
| 52 | + event.stopPropagation(); |
| 53 | + |
| 54 | + // Close the dropdown |
| 55 | + userDropdownOpen = false; |
| 56 | + |
| 57 | + // Navigate to the intended URL |
| 58 | + window.location.href = href; |
| 59 | + }; |
| 60 | +
|
| 61 | + const handleDropdownClick = (event) => { |
| 62 | + // Prevent clicks inside dropdown from bubbling up |
| 63 | + event.stopPropagation(); |
| 64 | + }; |
| 65 | +
|
| 66 | + const handleClickOutside = (event) => { |
| 67 | + if (userDropdownOpen && dropdownRef && !dropdownRef.contains(event.target)) { |
| 68 | + userDropdownOpen = false; |
| 69 | + } |
| 70 | + }; |
| 71 | +
|
| 72 | + // Add click outside listener |
| 73 | + $effect(() => { |
| 74 | + if (typeof document !== 'undefined') { |
| 75 | + document.addEventListener('click', handleClickOutside); |
| 76 | + return () => { |
| 77 | + document.removeEventListener('click', handleClickOutside); |
| 78 | + }; |
| 79 | + } |
| 80 | + }); |
| 81 | +
|
49 | 82 | let mainSidebarUrl = $derived($page.url.pathname); |
50 | 83 | let openDropdowns = $state({}); |
51 | 84 |
|
|
86 | 119 | ] |
87 | 120 | }, |
88 | 121 | { |
89 | | - href: '/app/accounts', |
| 122 | + key: 'accounts', |
90 | 123 | label: 'Accounts', |
91 | 124 | icon: Building, |
92 | | - type: 'link' |
| 125 | + type: 'dropdown', |
| 126 | + children: [ |
| 127 | + { href: '/app/accounts', label: 'All Accounts', icon: List }, |
| 128 | + { href: '/app/accounts/new', label: 'New Account', icon: Plus } |
| 129 | + ] |
93 | 130 | }, |
94 | 131 | { |
95 | 132 | key: 'opportunities', |
|
205 | 242 | </nav> |
206 | 243 | </div> |
207 | 244 |
|
208 | | - <!-- User profile section - moved to bottom --> |
209 | | - <div class="p-4 border-t border-gray-200 dark:border-gray-700"> |
| 245 | + <!-- settings section --> |
| 246 | + <div class="p-4 border-t border-gray-200 dark:border-gray-700" bind:this={dropdownRef}> |
210 | 247 | <div class="flex items-center gap-3 mb-3"> |
211 | 248 | <img class="w-10 h-10 rounded-lg object-cover" src={user.profilePhoto} alt="User avatar" /> |
212 | 249 | <div class="flex-1 min-w-0"> |
|
238 | 275 | </button> |
239 | 276 | </div> |
240 | 277 |
|
241 | | - <!-- User dropdown menu --> |
| 278 | + <!-- settings dropdown menu --> |
242 | 279 | {#if userDropdownOpen} |
243 | | - <div class="mt-3 p-1 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"> |
244 | | - <a |
245 | | - href="/app/profile" |
246 | | - class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors" |
| 280 | + <div |
| 281 | + class="mt-3 p-1 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700" |
| 282 | + onclick={handleDropdownClick} |
| 283 | + onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleDropdownClick(e); }} |
| 284 | + tabindex="0" |
| 285 | + role="menu" |
| 286 | + > |
| 287 | + <button |
| 288 | + type="button" |
| 289 | + onclick={(e) => handleSettingsLinkClick(e, '/app/profile')} |
| 290 | + class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors w-full text-left" |
247 | 291 | > |
248 | 292 | <User class="w-4 h-4" /> |
249 | 293 | Profile |
250 | | - </a> |
251 | | - <a |
252 | | - href="/app/users" |
253 | | - class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors" |
| 294 | + </button> |
| 295 | + <button |
| 296 | + type="button" |
| 297 | + onclick={(e) => handleSettingsLinkClick(e, '/app/users')} |
| 298 | + class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors w-full text-left" |
254 | 299 | > |
255 | 300 | <Users class="w-4 h-4" /> |
256 | 301 | Users |
257 | | - </a> |
258 | | - <a |
259 | | - href="/org" |
260 | | - class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors" |
| 302 | + </button> |
| 303 | + <button |
| 304 | + type="button" |
| 305 | + onclick={(e) => handleSettingsLinkClick(e, '/org')} |
| 306 | + class="flex items-center gap-3 px-3 py-2 text-sm text-gray-700 hover:bg-white dark:text-gray-300 dark:hover:bg-gray-700 rounded transition-colors w-full text-left" |
261 | 307 | > |
262 | 308 | <Building class="w-4 h-4" /> |
263 | 309 | Organizations |
264 | | - </a> |
| 310 | + </button> |
265 | 311 | <hr class="my-1 border-gray-200 dark:border-gray-600" /> |
266 | | - <a |
267 | | - href="/logout" |
268 | | - class="flex items-center gap-3 px-3 py-2 text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20 rounded transition-colors" |
| 312 | + <button |
| 313 | + type="button" |
| 314 | + onclick={(e) => handleSettingsLinkClick(e, '/logout')} |
| 315 | + class="flex items-center gap-3 px-3 py-2 text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20 rounded transition-colors w-full text-left" |
269 | 316 | > |
270 | 317 | <LogOut class="w-4 h-4" /> |
271 | 318 | Sign out |
272 | | - </a> |
| 319 | + </button> |
273 | 320 | </div> |
274 | 321 | {/if} |
275 | 322 | </div> |
|
0 commit comments