Add completion buttons to agenda tasks
Agenda items were plain links — completing a task required navigating
to the series page. Reuses the existing complete-form/button pattern
at a smaller scale so users can check off upcoming tasks in place.
Also tightens flash bar layout: centers items vertically, spreads
undo/close to edges via flex, and reduces inline padding.
Assisted-by: Claude Opus 4.6 via Claude Code
diff --git a/lib/ketchup/views/dashboard.rb b/lib/ketchup/views/dashboard.rb
index e784314..ed64475 100644
--- a/lib/ketchup/views/dashboard.rb
+++ b/lib/ketchup/views/dashboard.rb
@@ -115,10 +115,17 @@ module Views
div(class: "agenda-day-header") { friendly_day(date, offset) }
day_tasks.each do |task|
task_name = task[:note].lines.first&.strip || task[:note]
- a(
- href: "/series/#{task[:series_id]}",
- class: "agenda-day-pill"
- ) { task_name }
+ complete_path = "/series/#{task[:series_id]}/tasks/#{task[:id]}/complete"
+
+ div(class: "agenda-task") do
+ form(method: "post", action: complete_path, class: "complete-form") do
+ input(type: "hidden", name: "_csrf", value: @csrf.call(complete_path))
+ input(type: "hidden", name: "return_to", value: "/")
+ button(type: "submit", title: "Complete", class: "complete-btn",
+ **{ "aria-label": "Complete #{task_name}" }) { "\u2713" }
+ end
+ a(href: "/series/#{task[:series_id]}", class: "agenda-day-pill") { task_name }
+ end
end
end
end
diff --git a/public/css/app.css b/public/css/app.css
index 5d27525..166ed55 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -113,15 +113,20 @@ h2 { font-size: var(--step-0); font-weight: 600; }
right: var(--space-s);
z-index: 100;
display: flex;
- align-items: baseline;
+ align-items: center;
gap: var(--space-xs);
- padding: var(--space-xs) var(--space-l);
+ padding: var(--space-xs) var(--space-s);
color: #333;
font-size: var(--step--2);
background: #fff;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ min-width: 20rem;
+}
+
+.flash-message {
+ flex: 1;
}
@@ -257,22 +262,35 @@ h2 { font-size: var(--step-0); font-weight: 600; }
color: #222;
}
+.agenda-task {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2xs);
+ margin-block-end: 3px;
+}
+
+.agenda-task .complete-btn {
+ width: 14px;
+ height: 14px;
+ font-size: 10px;
+ border-width: 1px;
+ top: 0;
+}
+
.agenda-day-pill {
display: block;
font-size: var(--step--2);
- padding: 3px 6px;
- background: #f0f0f0;
+ padding: 3px 0;
color: #222;
- border-radius: 4px;
- margin-block-end: 3px;
text-decoration: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ min-width: 0;
}
.agenda-day-pill:hover {
- background: #e8e8e8;
+ color: #555;
}
/* -------------------- */