feat(ui): add theme-aware stats and finance carousel

This commit is contained in:
poyrazavsever
2026-07-17 21:56:52 +03:00
parent cb2ed90046
commit 49c4c370c8
7 changed files with 253 additions and 161 deletions
+75 -1
View File
@@ -22,6 +22,10 @@ assert.ok(
globalsCss.includes('@import "poyraz-ui/preset.css";'),
"Poyraz UI preset must be imported by app/globals.css",
);
assert.ok(
globalsCss.includes("@custom-variant dark (&:where(.dark, .dark *));"),
"Tailwind dark utilities must follow Neta's explicit root color mode",
);
for (const component of [
"SidebarProvider",
@@ -62,7 +66,11 @@ assert.doesNotMatch(
assert.match(settingsPage, /\bRadioGroup\b/, "Settings must use the Poyraz RadioGroup for theme selection");
for (const workspaceControl of [
'name="workspaceName"',
'name="logo"',
'name="metaTitle"',
'name="shortName"',
'name="lightLogo"',
'name="darkLogo"',
'name="favicon"',
'name="primaryColor"',
]) {
assert.ok(
@@ -70,6 +78,12 @@ for (const workspaceControl of [
`Settings must expose workspace branding control ${workspaceControl}`,
);
}
assert.ok(settingsPage.includes('useState("Genel")'), "Workspace and appearance settings must share the General tab");
assert.doesNotMatch(
settingsPage,
/\{\s*name:\s*"Görünüm"/,
"Appearance must not remain as a separate settings tab",
);
for (const colorMode of ["light", "dark", "system"]) {
assert.ok(
settingsPage.includes(`value: "${colorMode}"`),
@@ -88,17 +102,77 @@ assert.ok(
fs.existsSync(path.join(repoRoot, "server/settings/preferences.ts")),
"Missing database-backed user preferences service",
);
assert.match(
settingsPage,
/md:sticky md:top-8/,
"The desktop settings navigation must remain sticky while its content scrolls",
);
assert.equal(
fs.existsSync(path.join(repoRoot, "app/favicon.ico")),
false,
"Static App Router favicon must not override database-backed branding metadata",
);
const requiredSystemCompositions = [
"components/system/page-header.tsx",
"components/system/feedback-state.tsx",
"components/system/status-badge.tsx",
"components/system/destructive-confirmation.tsx",
"components/system/stat-card.tsx",
];
for (const file of requiredSystemCompositions) {
assert.ok(fs.existsSync(path.join(repoRoot, file)), `Missing Neta system composition: ${file}`);
}
const statCard = fs.readFileSync(
path.join(repoRoot, "components/system/stat-card.tsx"),
"utf8",
);
for (const semanticTone of [
"bg-success text-success-icon",
"bg-info text-info-icon",
"bg-warning text-warning-icon",
"bg-destructive-muted text-destructive-muted-foreground",
]) {
assert.ok(
statCard.includes(semanticTone),
`Stat cards must use Poyraz's theme-aware ${semanticTone} tokens`,
);
}
for (const statPage of [
"app/(dashboard)/dashboard-client.tsx",
"app/(dashboard)/clients/clients-client.tsx",
"app/(dashboard)/projects/projects-client.tsx",
"app/(dashboard)/journal/journal-client.tsx",
"app/(dashboard)/finance/finance-client.tsx",
]) {
const content = fs.readFileSync(path.join(repoRoot, statPage), "utf8");
assert.ok(
content.includes('from "@/components/system/stat-card"'),
`${statPage} must use the shared theme-aware stat card`,
);
}
const financePage = fs.readFileSync(
path.join(repoRoot, "app/(dashboard)/finance/finance-client.tsx"),
"utf8",
);
for (const sliderBehavior of [
"financeSummaryCardConfig",
"featured: true",
"snap-mandatory",
"overflow-x-auto",
"scrollBy",
'event.key === "ArrowLeft"',
'event.key === "ArrowRight"',
]) {
assert.ok(
financePage.includes(sliderBehavior),
`Finance summary slider is missing ${sliderBehavior}`,
);
}
const allowedLocalUiFiles = new Set([
"pending-link.tsx",
"pending-submit-button.tsx",