Restructure Tasks as a master-detail board, like the Directory outreach board

Each task arrival (a full week's sheet, or sometimes a single one-off task)
is now its own card in a left-hand list; selecting one shows its full detail
on the right, reusing the same .ab-card/.ab-outreach-list/.ab-outreach-detail
styling as the Directory tab for visual consistency. Also drops the
placeholder narrative text under Notes and Reports.
This commit is contained in:
beantownbabe committed 2026-08-21 08:25:49 +02:00
1 parent 10deb08700
commit 798d35f4c9
1 file changed
+87 -42
+87 -42
View File
@@ -848,57 +848,19 @@
<div id="tab-tasks" class="tab-content">
<h2 style="margin: 0 0 6px; font-size: 1.3rem; font-weight: 800; color: #1b3a5c;">Weekly Tasks</h2>
<p class="narrative">Peter's weekly task sheet (~/Downloads/Mckinley_Weekly_Task_Plan_*.xlsx) — a new one arrives about once a week; each week gets its own card below, newest first. [Placeholder — add a new card each week rather than overwriting the last one.]</p>
<p class="narrative">Peter's task assignments — usually a full week's sheet (~/Downloads/Mckinley_Weekly_Task_Plan_*.xlsx), sometimes just a single one-off task. Each arrival gets its own card on the left, newest first; select one to see its full detail. [Placeholder — add a new entry to TASKS_DATA each time Peter sends one.]</p>
<div class="card">
<h3>Week of 17–21 Aug 2026</h3>
<table class="crm-detail-table">
<thead>
<tr><th>Subtask</th><th>Ask</th><th>KPI</th><th>Status</th></tr>
</thead>
<tbody>
<tr>
<td>PE companies</td>
<td>Search LinkedIn for employees of power electronics companies from Peter's market research</td>
<td>&gt;10 people</td>
<td>Still open</td>
</tr>
<tr>
<td>SPIE attendees</td>
<td>Check whether employees of those same PE companies attend SPIE O&amp;P 2026</td>
<td>&gt;10</td>
<td>Still open, blocked on PE companies task above</td>
</tr>
<tr>
<td>Message draft</td>
<td>Design first-contact info material to send</td>
<td>&gt;2</td>
<td>Done</td>
</tr>
<tr>
<td>IPP for CRM</td>
<td>Define CRM requirements, stay solution-unbiased</td>
<td>—</td>
<td>Done</td>
</tr>
<tr>
<td>LinkedIn Posts</td>
<td>Continue posts per the Canva whiteboard</td>
<td>4 posts</td>
<td>Ongoing</td>
</tr>
</tbody>
</table>
<div class="ab-outreach" style="display: flex;">
<div class="ab-outreach-list" id="tasks-list"></div>
<div class="ab-outreach-detail" id="tasks-detail"></div>
</div>
<div class="card">
<h2>Notes</h2>
<p class="narrative">[Placeholder — quick notes go here.]</p>
</div>
<div class="card">
<h2>Reports</h2>
<p class="narrative">Mckinley's own reports to Peter on completed weekly tasks — not related to the LinkedIn Analytics End of Month Report. [Placeholder — add each report here once written.]</p>
</div>
</div>
@@ -6264,6 +6226,89 @@
document.getElementById("ab-view-board-btn").click();
document.querySelector(".ab-filter-chip[data-source=\"Outreach\"]").click();
/* ---- Tasks: Peter's weekly (sometimes single-task) assignments, master-detail like the
Directory outreach board -- a list of arrivals on the left, full detail on the right.
Reuses .ab-card/.ab-outreach-list/.ab-outreach-detail styling for visual consistency. */
var TASKS_DATA = [
{
id: "week-2026-08-17",
label: "Week of 17–21 Aug 2026",
subtasks: [
{ subtask: "PE companies", ask: "Search LinkedIn for employees of power electronics companies from Peter's market research", kpi: ">10 people", status: "Still open" },
{ subtask: "SPIE attendees", ask: "Check whether employees of those same PE companies attend SPIE O&P 2026", kpi: ">10", status: "Still open, blocked on PE companies task above" },
{ subtask: "Message draft", ask: "Design first-contact info material to send", kpi: ">2", status: "Done" },
{ subtask: "IPP for CRM", ask: "Define CRM requirements, stay solution-unbiased", kpi: "—", status: "Done" },
{ subtask: "LinkedIn Posts", ask: "Continue posts per the Canva whiteboard", kpi: "4 posts", status: "Ongoing" }
]
}
];
var tasksSelectedId = null;
function tasksEsc(s) {
return String(s == null ? "" : s).replace(/[&<>"]/g, function (c) {
return { "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;" }[c];
});
}
function renderTasksBoard() {
var sorted = TASKS_DATA; // newest-first order is authored order for now
if (!tasksSelectedId || !sorted.some(function (t) { return t.id === tasksSelectedId; })) {
tasksSelectedId = sorted.length ? sorted[0].id : null;
}
var list = document.getElementById("tasks-list");
list.innerHTML = "";
sorted.forEach(function (entry) {
list.appendChild(buildTaskSidebarCard(entry, entry.id === tasksSelectedId));
});
var detail = document.getElementById("tasks-detail");
var selected = sorted.filter(function (t) { return t.id === tasksSelectedId; })[0];
detail.innerHTML = selected ? buildTaskDetail(selected) : "<div class=\"ab-outreach-empty\">No tasks yet.</div>";
}
function buildTaskSidebarCard(entry, isSelected) {
var card = document.createElement("div");
card.className = "ab-card" + (isSelected ? " selected" : "");
card.dataset.id = entry.id;
var openCount = entry.subtasks.filter(function (s) { return s.status.indexOf("Done") !== 0; }).length;
var summary = entry.subtasks.length === 1
? entry.subtasks[0].status
: (openCount === 0 ? "All done" : openCount + " still open");
card.innerHTML =
"<div class=\"ab-card-top\">" +
"<div class=\"ab-card-company\">" + tasksEsc(entry.label) + "</div>" +
"<span class=\"ab-source-chip boss\">" + tasksEsc(summary) + "</span>" +
"</div>" +
"<div class=\"ab-card-name\">" + entry.subtasks.length + (entry.subtasks.length === 1 ? " task" : " subtasks") + "</div>";
card.addEventListener("click", function () {
tasksSelectedId = entry.id;
renderTasksBoard();
});
return card;
}
function buildTaskDetail(entry) {
var rows = entry.subtasks.map(function (s) {
return "<tr><td>" + tasksEsc(s.subtask) + "</td><td>" + tasksEsc(s.ask) + "</td><td>" + tasksEsc(s.kpi) + "</td><td>" + tasksEsc(s.status) + "</td></tr>";
}).join("");
return (
"<div class=\"card\">" +
"<h3>" + tasksEsc(entry.label) + "</h3>" +
"<table class=\"crm-detail-table\">" +
"<thead><tr><th>Subtask</th><th>Ask</th><th>KPI</th><th>Status</th></tr></thead>" +
"<tbody>" + rows + "</tbody>" +
"</table>" +
"</div>"
);
}
renderTasksBoard();
/* ---- Opportunities module loader ----
Fetches its markup, injects it into the empty tab container, then loads its
script as a normal <script src> (so it runs only once the DOM it needs exists). */