feat: track received image outcomes

This commit is contained in:
jjbrunton committed 2026-08-08 18:53:11 +01:00
1 parent 50de1c180d
commit d819a0f1e6
15 files changed
+145 -21

No files matched your search

@@ -40,7 +40,7 @@ function PerformanceTable({
return (
<div className="table-scroll">
<table aria-label={label} className="performance-table">
<thead><tr><th scope="col">Name</th><th scope="col">Responses</th><th scope="col">Rate</th><th scope="col">Sample</th></tr></thead>
<thead><tr><th scope="col">Name</th><th scope="col">Responses</th><th scope="col">Response rate</th><th scope="col">Images</th><th scope="col">Image rate</th><th scope="col">Sample</th></tr></thead>
<tbody>
{rows.map((row) => (
<tr key={rowLabel(row)}>
@@ -50,6 +50,8 @@ function PerformanceTable({
</th>
<td>{row.totalResponses}</td>
<td>{row.responseRate}%</td>
<td>{row.totalImages}</td>
<td>{row.imageRate}%</td>
<td><SampleSize totalSent={row.totalSent} /></td>
</tr>
))}
@@ -67,6 +69,7 @@ function Trend({ rows }: { rows: readonly DailyTrend[] }) {
<time dateTime={row.date}>{row.date}</time>
<span className="trend-track" aria-hidden="true"><span style={{ width: `${Math.max(2, Math.min(100, row.responseRate))}%` }} /></span>
<strong>{row.responseRate}%</strong>
<span>{row.totalImages} images ({row.imageRate}%)</span>
<SampleSize totalSent={row.totalSent} />
</li>
))}
@@ -82,7 +85,7 @@ function SuccessfulExamples({ examples }: { examples: readonly SuccessfulExample
const source = example.subreddit ?? 'unknown source';
return (
<article aria-label={`Successful example from ${source}`} className="successful-example" key={example.id}>
<div><span className="pill success">Response received</span><small>{source}</small></div>
<div><span className="pill success">Response received</span>{example.gotImage ? <span className="pill success">Image received</span> : null}<small>{source}</small></div>
{example.postTitle ? <h3>{example.postTitle}</h3> : null}
<blockquote>{example.originalMessage}</blockquote>
{example.responseSnippet ? <p><strong>Reply:</strong> {example.responseSnippet}</p> : null}
@@ -109,7 +112,7 @@ export function PerformancePage() {
return (
<div className="page performance-page">
<header className="page-header"><div><span className="eyebrow">Decision support</span><h1>Performance</h1><p>Compare response outcomes without hiding the sample sizes behind the percentages.</p></div></header>
<header className="page-header"><div><span className="eyebrow">Decision support</span><h1>Performance</h1><p>Compare response and received-image outcomes without hiding the sample sizes behind the percentages.</p></div></header>
<section aria-labelledby="trend-heading" className="panel feature-panel"><div className="panel-heading"><div><span className="eyebrow">Last 30 days</span><h2 id="trend-heading">Response trend</h2></div></div><Trend rows={trend.data ?? []} /></section>
<div className="performance-grid">
<section aria-labelledby="subreddit-heading" className="panel feature-panel"><div className="panel-heading"><h2 id="subreddit-heading">By subreddit</h2></div><PerformanceTable label="Subreddit performance" rows={subreddits.data ?? []} rowLabel={(row) => 'subreddit' in row ? row.subreddit : row.strategyId} /></section>
@@ -10,7 +10,7 @@
.confidence-warning { color: var(--warning); }
.sample-size { white-space: nowrap; color: var(--muted); }
.trend-list { display: grid; gap: .65rem; padding: 0; margin: 0; list-style: none; }
.trend-list li { display: grid; grid-template-columns: 6.5rem minmax(5rem, 1fr) 3rem 6rem; align-items: center; gap: .75rem; }
.trend-list li { display: grid; grid-template-columns: 6.5rem minmax(5rem, 1fr) 3rem 8rem 6rem; align-items: center; gap: .75rem; }
.trend-track { height: .5rem; overflow: hidden; background: var(--border); border-radius: 999px; }
.trend-track span { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
.example-grid { display: grid; gap: .75rem; }