diff --git a/frontend/src/viewers/CtePlanViewer.test.tsx b/frontend/src/viewers/CtePlanViewer.test.tsx
index 925513a7..aeab867d 100644
--- a/frontend/src/viewers/CtePlanViewer.test.tsx
+++ b/frontend/src/viewers/CtePlanViewer.test.tsx
@@ -68,19 +68,15 @@ test("renders strategy, question, and a chain strip with CTE names in order", ()
expect(screen.getAllByText("impianti_recenti").length).toBeGreaterThan(0);
});
-test("uses compact vertical and responsive lateral CTE card padding", () => {
+test("uses compact CTE section rhythm with moderate lateral padding", () => {
const { container } = render();
-
for (const header of container.querySelectorAll('[data-slot="card-header"]')) {
- expect(header).toHaveClass("px-3", "py-2", "sm:px-4", "[&.border-b]:pb-2");
- expect(header).not.toHaveClass("p-4", "sm:p-5", "sm:[&.border-b]:pb-5");
+ expect(header).toHaveClass("gap-2", "px-3", "py-2", "sm:px-4", "[&.border-b]:pb-2");
+ expect(header).not.toHaveClass("gap-3", "p-4", "sm:p-5");
}
for (const content of container.querySelectorAll('[data-slot="card-content"]')) {
- expect(content).toHaveClass("px-3", "py-2", "sm:px-4");
- expect(content).not.toHaveClass("p-4", "sm:p-5");
- }
- for (const card of container.querySelectorAll('[data-slot="card"]')) {
- expect(card).toHaveClass("shadow-none");
+ expect(content).toHaveClass("gap-3", "px-3", "py-2", "sm:px-4");
+ expect(content).not.toHaveClass("gap-5", "p-4", "sm:p-5");
}
});
@@ -142,7 +138,7 @@ test("groups filters in one bordered divided list with accessible padded rows",
expect(list).toHaveClass("border", "divide-y");
for (const filter of filters) {
expect(filter.parentElement).toBe(list);
- expect(filter).toHaveClass("px-3", "py-2", "sm:px-4");
+ expect(filter).toHaveClass("px-3", "py-1", "sm:px-4");
expect(filter).not.toHaveClass("p-3", "sm:p-4");
}
lists.push(list!);
@@ -161,22 +157,23 @@ test("renders rationale as a plain top-divided section", () => {
expect(rationale).not.toHaveClass("border-l-2", "bg-primary/5", "rounded-lg");
});
-test("uses the same compact padding for table rows and rationale dividers", () => {
+test("compacts table, filter, detail, and rationale rows", () => {
render();
const card = getCteCard("pazienti_idonei");
- const tableName = within(card).getByText("pazienti");
- expect(tableName.parentElement).toHaveClass("px-3", "py-2", "sm:px-4");
- expect(tableName.parentElement).not.toHaveClass("p-3", "sm:p-4");
+ const tableRow = within(card).getByText("pazienti").parentElement;
+ expect(tableRow).toHaveClass("px-3", "py-1", "sm:px-4");
- const filterRationale = within(card).getByText("Solo pazienti in follow-up").parentElement;
- expect(filterRationale).toHaveClass("pt-2");
- expect(filterRationale).not.toHaveClass("pt-3");
+ const filter = within(card).getByRole("group", { name: "Filter 1" });
+ expect(filter).toHaveClass("space-y-2", "px-3", "py-1", "sm:px-4");
+ expect(filter.firstElementChild).toHaveClass("gap-2");
+ const filterDetails = within(card).getByText("Solo pazienti in follow-up").parentElement;
+ expect(filterDetails).toHaveClass("gap-y-1", "pt-1");
- const cteRationale = within(card)
+ const rationale = within(card)
.getByText("Base della catena: riduce il volume prima dei join")
.closest("section");
- expect(cteRationale).toHaveClass("border-t", "pt-2");
- expect(cteRationale).not.toHaveClass("pt-4");
+ expect(rationale).toHaveClass("pt-1");
+ expect(within(rationale!).getByText("Rationale")).toHaveClass("mb-1");
});
test("shows 'no dependencies' for a CTE with an empty depends_on", () => {
diff --git a/frontend/src/viewers/CtePlanViewer.tsx b/frontend/src/viewers/CtePlanViewer.tsx
index 4e95c051..53e5138e 100644
--- a/frontend/src/viewers/CtePlanViewer.tsx
+++ b/frontend/src/viewers/CtePlanViewer.tsx
@@ -16,34 +16,34 @@ function FilterRow({ filter, index }: { filter: CtePlanFilter; index: number })
-
+
Column
-
+
{filter.column}
{(filter.description || filter.rationale) && (
-
+
{filter.description && (
<>
Description
-
+
{filter.description}
>
@@ -51,7 +51,7 @@ function FilterRow({ filter, index }: { filter: CtePlanFilter; index: number })
{filter.rationale && (
<>
Rationale
-
+
{filter.rationale}
>
@@ -67,25 +67,25 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
return (
-
+
CTE {cte.index}/{total}
-
+
{cte.name}
{cte.purpose && (
-
+
{cte.purpose}
)}
-
-
+
+
- Depends on
+ Depends on
{dependsOn.length ? (
{dependsOn.map((dependency) => (
@@ -99,7 +99,7 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
{cte.keys && cte.keys.length > 0 && (
- Keys
+ Keys
{cte.keys.map((key) => (
{key}
@@ -111,18 +111,18 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
{cte.tables && cte.tables.length > 0 && (
- Tables
+ Tables
{cte.tables.map((table) => (
-
+
{table.name}
{table.description && (
-
+
{table.description}
)}
@@ -134,7 +134,7 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
{cte.filters && cte.filters.length > 0 && (
- Filters
+ Filters
{cte.filters.map((f, i) => (
@@ -145,7 +145,7 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
{cte.output_columns && cte.output_columns.length > 0 && (
- Output columns
+ Output columns
{cte.output_columns.map((column) => (
{column}
@@ -155,9 +155,9 @@ function CteCard({ cte, total }: { cte: CtePlanCte; total: number }) {
)}
{cte.rationale && (
-
- Rationale
-
+
+ Rationale
+
{cte.rationale}