diff --git a/app/views/assignments/by_user.html.erb b/app/views/assignments/by_user.html.erb index a707a7402baeb6c8d0ffe5ce19f9f47a11463793..0f3e989325fd1ecd04ae92833f05f4c1bce8568c 100644 --- a/app/views/assignments/by_user.html.erb +++ b/app/views/assignments/by_user.html.erb @@ -1,12 +1,23 @@ <div class="container mx-auto px-4 py-8"> <div class="max-w-full"> - <div class="flex items-center mb-6"> - <h1 class="text-2xl font-bold dark:text-gray-200"> - Assignments for - <%= link_to @user.name, user_assignments_path(@user), class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %> - </h1> - <%= link_to user_assignments_path(@user, format: 'ics'), class: "btn btn-info-light ml-4" do %> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal + <div class="flex items-center justify-between mb-6"> + <div class="flex items-center"> + <h1 class="text-2xl font-bold dark:text-gray-200"> + Assignments for + <%= link_to @user.name, user_assignments_path(@user), class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %> + </h1> + <%= link_to user_assignments_path(@user, format: 'ics'), class: "btn btn-info-light ml-4" do %> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal + <% end %> + </div> + <% if @active_candidates %> + <div class="flex items-center"> + <label class="inline-flex items-center cursor-pointer"> + <input type="checkbox" id="showCandidates" class="sr-only peer" checked> + <div class="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div> + <span class="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show unconfirmed sessions</span> + </label> + </div> <% end %> </div> <% now = Time.now %> @@ -130,33 +141,105 @@ document.addEventListener('turbo:load', function() { const tabButtons = document.querySelectorAll('[data-tabs-target]'); const tabContents = document.querySelectorAll('[role="tabpanel"]'); + const showCandidatesCheckbox = document.getElementById('showCandidates'); + + // Function to switch tabs + function switchTab(targetId) { + const target = document.querySelector(targetId); + const button = document.querySelector(`[data-tabs-target="${targetId}"]`); + + if (!target || !button) return; + + // Hide all tabs + tabContents.forEach(content => { + content.classList.add('hidden'); + content.classList.remove('block'); + }); + + // Remove active state from all buttons + tabButtons.forEach(btn => { + btn.classList.remove('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active'); + btn.classList.add('text-gray-500', 'dark:text-gray-400', 'border-transparent'); + btn.setAttribute('aria-selected', 'false'); + }); + + // Show the selected tab + target.classList.remove('hidden'); + target.classList.add('block'); + + // Set active state on clicked button + button.classList.remove('text-gray-500', 'dark:text-gray-400', 'border-transparent'); + button.classList.add('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active'); + button.setAttribute('aria-selected', 'true'); + + // Update URL hash + const viewName = targetId === '#listViewTab' ? 'list' : 'table'; + window.history.replaceState(null, null, `#${viewName}`); + } + // Handle tab clicks tabButtons.forEach(button => { button.addEventListener('click', () => { - const target = document.querySelector(button.dataset.tabsTarget); - - // Hide all tabs - tabContents.forEach(content => { - content.classList.add('hidden'); - content.classList.remove('block'); + switchTab(button.dataset.tabsTarget); + }); + }); + + // Handle initial load based on URL hash + const hash = window.location.hash; + if (hash === '#table') { + switchTab('#tableViewTab'); + } else if (hash === '#list' || !hash) { + switchTab('#listViewTab'); + } + + // Handle candidate filter + if (showCandidatesCheckbox) { + // Function to toggle candidate visibility + function toggleCandidates(show) { + // For table view - find rows with yellow background + const candidateTableRows = document.querySelectorAll('tr.bg-yellow-50'); + candidateTableRows.forEach(row => { + if (show) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } }); - // Remove active state from all buttons - tabButtons.forEach(btn => { - btn.classList.remove('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active'); - btn.classList.add('text-gray-500', 'dark:text-gray-400', 'border-transparent'); - btn.setAttribute('aria-selected', 'false'); + // For list view - find list items that contain the CANDIDATE badge + const listItems = document.querySelectorAll('#listViewTab li'); + listItems.forEach(item => { + const hasCandidate = item.querySelector('.bg-yellow-100'); + if (hasCandidate) { + if (show) { + item.style.display = ''; + } else { + item.style.display = 'none'; + } + } }); - // Show the selected tab - target.classList.remove('hidden'); - target.classList.add('block'); - - // Set active state on clicked button - button.classList.remove('text-gray-500', 'dark:text-gray-400', 'border-transparent'); - button.classList.add('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active'); - button.setAttribute('aria-selected', 'true'); + // Also hide/show date headers if all items in that date are hidden + document.querySelectorAll('#listViewTab .mb-6').forEach(dateGroup => { + const listItems = dateGroup.querySelectorAll('li'); + if (listItems.length > 0) { + const visibleItems = Array.from(listItems).filter(item => item.style.display !== 'none'); + if (visibleItems.length === 0) { + dateGroup.style.display = 'none'; + } else { + dateGroup.style.display = ''; + } + } + }); + } + + // Initial state + toggleCandidates(showCandidatesCheckbox.checked); + + // Handle checkbox changes + showCandidatesCheckbox.addEventListener('change', function() { + toggleCandidates(this.checked); }); - }); + } }); </script>