Skip to content

Commit f386fa3

Browse files
subodhkjclaude
andcommitted
feat(executive-dashboard): filter weekly trends to last month + add form type filter
- Weekly Trends table now shows only weeks overlapping the latest complete month (W14–W18 for April 2026, filtered via startDate/endDate overlap) - Section sub-text reflects the filtered range (e.g. W14 – W18) - Added V1 / EDS / Both toggle buttons in the section header - Both: two rows per week with rowspan (existing layout) - V1 / EDS: single row per week with its own week cell - Filter buttons colour-coded: Both=navy, V1=blue, EDS=purple - Changed section-hdr alignment to center to accommodate the button group Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1cb4d9c commit f386fa3

1 file changed

Lines changed: 99 additions & 6 deletions

File tree

dashboards/executive-dashboard.js

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,34 @@ const STYLE = `
179179
/* ── Section headers ─────────────────────────────────────────────────── */
180180
.section-hdr{
181181
display:flex;
182-
align-items:baseline;
182+
align-items:center;
183183
gap:12px;
184184
margin-bottom:14px;
185185
}
186+
187+
/* ── Form filter buttons ─────────────────────────────────────────────── */
188+
.form-filter-btns{
189+
margin-left:auto;
190+
display:flex;
191+
gap:6px;
192+
align-items:center;
193+
}
194+
.form-filter-btn{
195+
padding:4px 12px;
196+
border-radius:6px;
197+
border:1px solid var(--border);
198+
background:white;
199+
font-size:11px;
200+
font-weight:600;
201+
color:var(--muted);
202+
cursor:pointer;
203+
transition:background .15s,color .15s,border-color .15s;
204+
font-family:'IBM Plex Sans',system-ui,sans-serif;
205+
}
206+
.form-filter-btn:hover{background:#f8fafc}
207+
.form-filter-btn.active[data-filter="both"]{background:var(--navy);color:white;border-color:var(--navy)}
208+
.form-filter-btn.active[data-filter="v1"]{background:var(--blue-lt);color:var(--blue);border-color:var(--blue-mid)}
209+
.form-filter-btn.active[data-filter="eds"]{background:var(--purple-lt);color:var(--purple);border-color:var(--purple-mid)}
186210
.section-hdr h2{
187211
font-family:'Playfair Display',Georgia,serif;
188212
font-size:20px;
@@ -816,8 +840,11 @@ function renderCallouts(callouts) {
816840
</div>`;
817841
}
818842

819-
function renderTrendsTable(weeks) {
820-
const latest = weeks[weeks.length - 1];
843+
function renderTrendsTable(weeks, formFilter = 'both') {
844+
if (!weeks.length) {
845+
return '<p class="empty" style="padding:16px;color:var(--muted)">No weekly data available.</p>';
846+
}
847+
const last = weeks[weeks.length - 1];
821848

822849
const thead = `
823850
<thead>
@@ -833,11 +860,44 @@ function renderTrendsTable(weeks) {
833860
</thead>`;
834861

835862
const rows = weeks.slice().reverse().map((w, i) => {
836-
const isLatest = w.week === latest.week;
863+
const isLatest = w.week === last.week;
837864
const isAlt = !isLatest && i % 2 === 1;
838865
const rowClass = isLatest ? 'row-latest' : isAlt ? 'row-group-alt' : '';
839866
const contClass = isLatest ? 'row-latest-cont' : isAlt ? 'row-group-alt-cont' : '';
840867

868+
const weekCell = `
869+
<td class="week-cell">
870+
<div class="week-num">${w.week || w.label}</div>
871+
<div class="week-dates">${w.dateRange || ''}</div>
872+
${w.reportUrl ? `<a class="report-link" href="${w.reportUrl}" target="_blank">Report ↗</a>` : ''}
873+
</td>`;
874+
875+
if (formFilter === 'v1') {
876+
return `
877+
<tr class="${rowClass}">
878+
${weekCell}
879+
<td><span class="form-badge form-v1">V1</span></td>
880+
<td class="num num-v1">${fmt(w.v1?.pageViews)}</td>
881+
<td class="num num-err">${fmt(w.v1?.jsErrors)}</td>
882+
<td class="num num-muted">${fmt(w.v1?.missingResources)}</td>
883+
<td class="num num-v1">${w.v1?.visibilityP50 || '—'}</td>
884+
<td class="num num-muted">${w.v1?.visibilityP75 || '—'}</td>
885+
</tr>`;
886+
}
887+
888+
if (formFilter === 'eds') {
889+
return `
890+
<tr class="${rowClass}">
891+
${weekCell}
892+
<td><span class="form-badge form-eds">EDS</span></td>
893+
<td class="num num-eds">${fmt(w.eds?.pageViews)}</td>
894+
<td class="num num-eds">${fmt(w.eds?.jsErrors)}</td>
895+
<td class="num num-muted">${fmt(w.eds?.missingResources)}</td>
896+
<td class="num num-eds">${w.eds?.visibilityP50 || '—'}</td>
897+
<td class="num num-muted">${w.eds?.visibilityP75 || '—'}</td>
898+
</tr>`;
899+
}
900+
841901
return `
842902
<tr class="${rowClass}">
843903
<td class="week-cell" rowspan="2">
@@ -974,6 +1034,19 @@ class ExecutiveDashboard extends HTMLElement {
9741034
? latestMonth.label.split(' ')[0].slice(0, 3).toUpperCase()
9751035
: (latest.week || latest.label);
9761036

1037+
const aprilWeeks = latestMonth
1038+
? weekly.filter(w => {
1039+
const wStart = new Date(w.startDate);
1040+
const wEnd = new Date(w.endDate);
1041+
const mStart = new Date(latestMonth.startDate);
1042+
const mEnd = new Date(latestMonth.endDate);
1043+
return wStart <= mEnd && wEnd >= mStart;
1044+
})
1045+
: weekly;
1046+
const trendsFirst = aprilWeeks[0]?.week || '';
1047+
const trendsLast = aprilWeeks[aprilWeeks.length - 1]?.week || '';
1048+
const trendsSubText = `${trendsFirst}${trendsLast} · one row per form type`;
1049+
9771050
wrapper.innerHTML = `
9781051
<div class="hero">
9791052
<div class="hero-left">
@@ -999,9 +1072,14 @@ class ExecutiveDashboard extends HTMLElement {
9991072
<div>
10001073
<div class="section-hdr">
10011074
<h2>Weekly Trends</h2>
1002-
<span class="section-sub">${weekly[0]?.week || ''}${latest.week || latest.label} · one row per form type</span>
1075+
<span class="section-sub">${trendsSubText}</span>
1076+
<div class="form-filter-btns" id="trends-filter-btns">
1077+
<button class="form-filter-btn active" data-filter="both">Both</button>
1078+
<button class="form-filter-btn" data-filter="v1">V1</button>
1079+
<button class="form-filter-btn" data-filter="eds">EDS</button>
1080+
</div>
10031081
</div>
1004-
${renderTrendsTable(weekly)}
1082+
<div id="trends-table-wrap">${renderTrendsTable(aprilWeeks)}</div>
10051083
</div>
10061084
10071085
<div class="monthly-section">
@@ -1017,6 +1095,21 @@ class ExecutiveDashboard extends HTMLElement {
10171095
</div>
10181096
10191097
</div>`;
1098+
1099+
// Wire up trends form filter
1100+
const filterBtns = shadow.getElementById('trends-filter-btns');
1101+
const trendsWrap = shadow.getElementById('trends-table-wrap');
1102+
if (filterBtns && trendsWrap) {
1103+
filterBtns.addEventListener('click', (e) => {
1104+
const btn = e.target.closest('[data-filter]');
1105+
if (!btn) {
1106+
return;
1107+
}
1108+
filterBtns.querySelectorAll('.form-filter-btn').forEach(b => b.classList.remove('active'));
1109+
btn.classList.add('active');
1110+
trendsWrap.innerHTML = renderTrendsTable(aprilWeeks, btn.dataset.filter);
1111+
});
1112+
}
10201113
}
10211114
}
10221115

0 commit comments

Comments
 (0)