Polish dashboard analytics and campaign layouts

This commit is contained in:
Matthias
2026-07-01 19:50:31 +02:00
parent 5db471fba4
commit f0b2c48073
9 changed files with 302 additions and 81 deletions

View File

@@ -22,7 +22,7 @@ test("campaign board renders campaigns as a desktop ledger with mobile records",
assert.doesNotMatch(source, /<th\b/i);
assert.doesNotMatch(source, /className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3"/);
assert.match(source, /2xl:grid-cols-\[minmax\(0,1fr\)_21rem\]/);
assert.match(source, /2xl:grid-cols-\[minmax\(0,1fr\)_20rem\]/);
assert.match(source, /campaign-ledger hidden 2xl:block/);
assert.match(source, /campaign-mobile-records grid gap-3 2xl:hidden/);
assert.match(source, /role="table"/);
@@ -36,6 +36,7 @@ test("campaign board renders campaigns as a desktop ledger with mobile records",
assert.match(source, /toggleCampaign\(campaign\)/);
assert.match(source, /runCampaign\(campaign\)/);
assert.match(source, /Suchlauf starten/);
assert.match(source, /aria-label=\{`\$\{campaign\.name\} Suchlauf starten`\}/);
assert.match(source, /Lead-Limit/);
assert.match(source, /Audit-Limit/);
assert.match(source, /Letzter Lauf/);
@@ -57,10 +58,11 @@ test("campaign board surfaces recent run logs", async () => {
assert.match(source, /campaign_cron_skipped/);
});
test("campaign ledger avoids clipping actions at desktop breakpoints", async () => {
test("campaign ledger fits desktop breakpoints without horizontal scroll", async () => {
const styles = await readFile(globalsPath, "utf8");
assert.match(styles, /\.campaign-ledger\s*{[\s\S]*overflow-x:\s*auto;/);
assert.doesNotMatch(styles, /\.campaign-ledger\s*{[\s\S]*overflow:\s*hidden;/);
assert.match(styles, /\.campaign-ledger-row\s*{[\s\S]*min-width:\s*58rem;/);
assert.match(styles, /\.campaign-ledger\s*{[\s\S]*overflow:\s*hidden;/);
assert.doesNotMatch(styles, /\.campaign-ledger\s*{[\s\S]*overflow-x:\s*auto;/);
assert.match(styles, /\.campaign-ledger-row\s*{[\s\S]*width:\s*100%;/);
assert.match(styles, /\.campaign-ledger-row\s*{[\s\S]*min-width:\s*0;/);
});

View File

@@ -11,6 +11,7 @@ const sidebarPath = join(
const authEntryPath = join(process.cwd(), "components", "auth-entry.tsx");
const layoutPath = join(process.cwd(), "app", "layout.tsx");
const globalsPath = join(process.cwd(), "app", "globals.css");
const themePath = join(process.cwd(), "components", "dashboard-theme.tsx");
test("dashboard sidebar uses PitchFast SaaS branding", async () => {
const source = await readFile(sidebarPath, "utf8");
@@ -31,6 +32,17 @@ test("light theme sidebar remains a light operational rail", async () => {
assert.match(darkBlock, /--sidebar:\s*oklch\(0\.13/);
});
test("desktop dashboard shell keeps sidebar height independent from content", async () => {
const sidebar = await readFile(sidebarPath, "utf8");
const theme = await readFile(themePath, "utf8");
assert.match(theme, /md:items-start/);
assert.match(sidebar, /md:h-dvh/);
assert.match(sidebar, /md:self-start/);
assert.match(sidebar, /md:overflow-y-auto/);
assert.doesNotMatch(sidebar, /md:min-h-dvh/);
});
test("public entry branding also uses PitchFast", async () => {
const authEntry = await readFile(authEntryPath, "utf8");
const layout = await readFile(layoutPath, "utf8");