diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-21 22:53:37 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-21 22:53:37 -1000 |
| commit | 583f90c5dedf0235fa45557359b0e6e7dd62b0f0 (patch) | |
| tree | 304e4527b6668669197fc9ffdf2ffc87566478f0 /web/templates/partials | |
| parent | dd4689a71de8f1c0b5a2d483827411a9645ad66a (diff) | |
Implement 10 UI/UX improvements and bug fixes
- Fix outdated Todoist task URL format (showTask -> app/task)
- Fix quick-add date defaulting to tomorrow in evening (client-side JS)
- Add tap-to-expand for task descriptions with checkbox completion
- Add visual differentiation: overdue (red), future (gray), today (normal)
- Sort tasks by urgency: overdue > today-timed > today-allday > future
- Keep completed tasks visible with strikethrough until refresh
- Add random Unsplash landscape background with content overlay
- Hide future tasks behind collapsible fold with count badge
- Unified modal menu for Quick Add + Bug Report (Ctrl+K shortcut)
- Click task title to edit description in modal
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'web/templates/partials')
| -rw-r--r-- | web/templates/partials/tasks-tab.html | 89 |
1 files changed, 76 insertions, 13 deletions
diff --git a/web/templates/partials/tasks-tab.html b/web/templates/partials/tasks-tab.html index 2a89a40..afbbe2c 100644 --- a/web/templates/partials/tasks-tab.html +++ b/web/templates/partials/tasks-tab.html @@ -10,7 +10,7 @@ onclick="document.getElementById('quick-add-form').classList.toggle('hidden')" class="w-full p-3 sm:p-4 text-left flex justify-between items-center"> <span class="font-semibold text-gray-900">+ Quick Add</span> - <span class="text-gray-400 text-sm">tap to expand</span> + <svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg> </button> <form id="quick-add-form" class="hidden p-3 sm:p-4 pt-0 border-t border-gray-100" @@ -28,8 +28,15 @@ <div> <input type="date" name="due_date" - value="{{.Today}}" + id="quick-add-date" class="border border-gray-300 rounded-lg px-2 py-2 text-sm focus:ring-2 focus:ring-primary-500"> + <script> + (function() { + var d = new Date(); + var dateStr = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0'); + document.getElementById('quick-add-date').value = dateStr; + })(); + </script> </div> <div> <select name="source" @@ -73,18 +80,23 @@ {{if .Atoms}} <div class="space-y-2"> {{range .Atoms}} - <div class="task-item bg-white rounded-lg p-3 sm:p-4 shadow-sm hover:shadow-md transition-shadow border-l-4 {{.ColorClass}} {{if .IsOverdue}}opacity-50{{end}}" - hx-post="/complete-atom" - hx-trigger="click" - hx-vals='{"id": "{{.ID}}", "source": "{{.Source}}"}' - hx-target="this" - hx-swap="outerHTML" - hx-confirm="Mark as complete?"> - <div class="flex items-start gap-2 sm:gap-3"> + <div class="task-item bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow border-l-4 {{.ColorClass}} {{if .IsFuture}}opacity-60{{end}}"> + <div class="flex items-start gap-2 sm:gap-3 p-3 sm:p-4"> + <!-- Checkbox for completing --> + <input type="checkbox" + hx-post="/complete-atom" + hx-vals='{"id": "{{.ID}}", "source": "{{.Source}}"}' + hx-target="closest .task-item" + hx-swap="outerHTML" + class="mt-1 h-5 w-5 rounded border-gray-300 text-primary-600 focus:ring-primary-500 cursor-pointer flex-shrink-0"> <span class="text-lg flex-shrink-0">{{.SourceIcon}}</span> <div class="flex-1 min-w-0"> <div class="flex items-start justify-between gap-2"> - <h3 class="text-sm font-medium {{if .IsOverdue}}text-gray-500{{else}}text-gray-900{{end}} break-words">{{.Title}}</h3> + <h3 class="text-sm {{if .IsOverdue}}text-red-600 font-semibold{{else if .IsFuture}}text-gray-400 font-normal{{else}}text-gray-900 font-medium{{end}} break-words cursor-pointer hover:underline" + hx-get="/tasks/detail?id={{.ID}}&source={{.Source}}" + hx-target="#task-edit-content" + hx-swap="innerHTML" + onclick="document.getElementById('task-edit-modal').classList.remove('hidden')">{{.Title}}</h3> {{if .URL}} <a href="{{.URL}}" target="_blank" class="text-primary-600 hover:text-primary-800 flex-shrink-0" onclick="event.stopPropagation()"> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> @@ -95,21 +107,72 @@ </div> <div class="flex flex-wrap items-center gap-2 mt-1 text-xs text-gray-400"> {{if .DueDate}} - <span class="{{if .IsOverdue}}text-red-400{{end}}">{{.DueDate.Format "Jan 2"}}{{if .HasSetTime}}, {{.DueDate.Format "3:04pm"}}{{end}}</span> + <span class="{{if .IsOverdue}}text-red-500 font-medium{{end}}">{{.DueDate.Format "Jan 2"}}{{if .HasSetTime}}, {{.DueDate.Format "3:04pm"}}{{end}}</span> {{end}} {{if gt .Priority 2}} <span class="text-red-500 font-medium">P{{.Priority}}</span> {{end}} + {{if .Description}} + <span class="text-gray-400">+details</span> + {{end}} </div> </div> </div> + {{if .Description}} + <details class="border-t border-gray-100"> + <summary class="px-3 sm:px-4 py-2 text-xs text-gray-500 cursor-pointer hover:bg-gray-50">Tap to expand</summary> + <div class="px-3 sm:px-4 pb-3 text-sm text-gray-600">{{.Description}}</div> + </details> + {{end}} </div> {{end}} </div> {{else}} <div class="bg-white/50 rounded-lg p-6 text-center"> - <p class="text-gray-500 text-sm">No tasks found.</p> + <p class="text-gray-500 text-sm">No current tasks.</p> </div> {{end}} + + <!-- Future Tasks (Collapsed by default) --> + {{if .FutureAtoms}} + <details class="mt-4"> + <summary class="bg-white/70 rounded-lg p-3 cursor-pointer hover:bg-white/90 transition-colors text-sm text-gray-600 flex items-center justify-between"> + <span>+{{len .FutureAtoms}} later</span> + <svg class="w-4 h-4 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg> + </summary> + <div class="space-y-2 mt-2"> + {{range .FutureAtoms}} + <div class="task-item bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow border-l-4 {{.ColorClass}} opacity-60"> + <div class="flex items-start gap-2 sm:gap-3 p-3 sm:p-4"> + <input type="checkbox" + hx-post="/complete-atom" + hx-vals='{"id": "{{.ID}}", "source": "{{.Source}}"}' + hx-target="closest .task-item" + hx-swap="outerHTML" + class="mt-1 h-5 w-5 rounded border-gray-300 text-primary-600 focus:ring-primary-500 cursor-pointer flex-shrink-0"> + <span class="text-lg flex-shrink-0">{{.SourceIcon}}</span> + <div class="flex-1 min-w-0"> + <div class="flex items-start justify-between gap-2"> + <h3 class="text-sm text-gray-400 font-normal break-words">{{.Title}}</h3> + {{if .URL}} + <a href="{{.URL}}" target="_blank" class="text-primary-600 hover:text-primary-800 flex-shrink-0"> + <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path> + </svg> + </a> + {{end}} + </div> + <div class="flex flex-wrap items-center gap-2 mt-1 text-xs text-gray-400"> + {{if .DueDate}} + <span>{{.DueDate.Format "Jan 2"}}{{if .HasSetTime}}, {{.DueDate.Format "3:04pm"}}{{end}}</span> + {{end}} + </div> + </div> + </div> + </div> + {{end}} + </div> + </details> + {{end}} </div> {{end}} |
