Listagens e tabelas
mad-pivot-table
mad-pivot-field
mad-pivot-row
mad-pivot-view
mad_validate acusa R045/R031 aqui — falsos positivos (schema desatualizado)
O schema do
mad_props pra mad-pivot-table conhece só ~13 props —
name, joins, além de label/aggregation/
format/currency em row/col/value/filter e area em
mad-pivot-field, existem de verdade (confirmado em
packages/mad-framework/src/mad/views/components/pivot-table.blade.php e em
MadGridCompiler::buildPivotFieldAttrs) mas disparam R045. O aviso R031 sobre
database="business" também é esperado aqui: neste projeto (mad-framework-laravel-teste)
"business" é a conexão real configurada — mesmo valor já usado no gabarito
(tutor.examples.forms-texto.db-combo). Vale reportar pra quem mantém o schema do MCP.
Básico (mad-pivot-row + mad-pivot-value)
Uma linha (categoria) e um valor agregado (soma). model + :joins resolvem a query sozinhos — zero PHP no controller.
Pedidos por categoria
resources/views/tutor/examples/grids-pivot/basico.blade.php
<mad-pivot-table name="tutor_pivot_basico" model="TutorDemoPedido" database="business"
:joins="['tutor_categorias' => ['categoria_id', 'tutor_categorias.id']]"
title="Pedidos por categoria" height="420">
<mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
<mad-pivot-value field="valor_total" label="Valor total"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Cross-tab (mad-pivot-row + mad-pivot-col)
Categoria nas linhas, estado do pedido nas colunas — dois joins pra trazer os dois nomes.
Categoria x Estado
resources/views/tutor/examples/grids-pivot/cross-tab.blade.php
<mad-pivot-table name="tutor_pivot_cross_tab" model="TutorDemoPedido" database="business"
:joins="[
'tutor_categorias' => ['categoria_id', 'tutor_categorias.id'],
'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
]"
title="Categoria x Estado" height="450">
<mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
<mad-pivot-col field="tutor_estados_pedido.nome" label="Estado" />
<mad-pivot-value field="valor_total" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Multi-nível com subtotais + mad-pivot-filter
Dois níveis de linha (estado > categoria) com subtotals, mais um filtro interativo por mês (SQL raw com alias).
Estado > Categoria (com subtotais e filtro por mês)
resources/views/tutor/examples/grids-pivot/subtotais.blade.php
<mad-pivot-table name="tutor_pivot_subtotais" model="TutorDemoPedido" database="business"
:joins="[
'tutor_categorias' => ['categoria_id', 'tutor_categorias.id'],
'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
]"
title="Estado > Categoria (com subtotais e filtro por mês)" height="500" subtotals>
<mad-pivot-row field="tutor_estados_pedido.nome" label="Estado" />
<mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
<mad-pivot-value field="valor_total" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-filter field="SUBSTR(dt_pedido,1,7) as mes" label="Mês (AAAA-MM)" />
</mad-pivot-table>
Múltiplas agregações do mesmo campo
valor_total três vezes: soma, média (ticket médio) e contagem de pedidos.
Categoria — múltiplas agregações
resources/views/tutor/examples/grids-pivot/multi-agregacao.blade.php
<mad-pivot-table name="tutor_pivot_multi_agregacao" model="TutorDemoPedido" database="business"
:joins="['tutor_categorias' => ['categoria_id', 'tutor_categorias.id']]"
title="Categoria — múltiplas agregações" height="420">
<mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
<mad-pivot-value field="valor_total" label="Total vendido"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-value field="valor_total" label="Ticket médio"
aggregation="avg" format="currency" currency="BRL" />
<mad-pivot-value field="id" label="Qtd. pedidos"
aggregation="count" format="number" />
</mad-pivot-table>
Catálogo de campos + views salvas (mad-pivot-field + mad-pivot-view)
Campos declarados uma vez em mad-pivot-field; duas mad-pivot-view viram presets que o usuário troca no seletor da UI.
Pedidos — catálogo de campos + views
resources/views/tutor/examples/grids-pivot/campos-views.blade.php
<mad-pivot-table name="tutor_pivot_campos_views" model="TutorDemoPedido" database="business"
:joins="[
'tutor_categorias' => ['categoria_id', 'tutor_categorias.id'],
'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
]"
title="Pedidos — catálogo de campos + views" height="500" field-list>
<mad-pivot-field field="tutor_categorias.nome" label="Categoria" area="rows" />
<mad-pivot-field field="tutor_estados_pedido.nome" label="Estado" area="columns" />
<mad-pivot-field field="valor_total" label="Valor" area="values"
aggregation="sum" format="currency-BRL" />
<mad-pivot-view name="Por categoria" default>
<mad-pivot-row field="tutor_categorias.nome" />
<mad-pivot-value field="valor_total" />
</mad-pivot-view>
<mad-pivot-view name="Categoria x Estado">
<mad-pivot-row field="tutor_categorias.nome" />
<mad-pivot-col field="tutor_estados_pedido.nome" />
<mad-pivot-value field="valor_total" />
</mad-pivot-view>
</mad-pivot-table>
Código-fonte completo da página
app/control/Tutor/TutorGridsPivot.php
<?php
namespace App\Control\Tutor;
use App\Support\Tutor\TutorDemoSeed;
use App\Support\Tutor\TutorPage;
/**
* TutorGridsPivot — catálogo grids_pivot.
*
* <mad-pivot-table> é 100% declarativo: `model=` + `database=` + `:joins`
* resolvem a query sozinhos (packages/mad-framework/src/mad/views/
* components/pivot-table.blade.php monta o SELECT via Query Builder e
* renderiza um iframe React em manager.madbuilder.com.br/mad-table — "Zero
* codigo PHP no controller" é literal, comentário no próprio arquivo). A doc
* do componente (components-admin/pivot-table.md) proíbe explicitamente
* "query manual + array_reduce no controller para depois passar pro Blade".
* Por isso esta página NÃO tem nenhum método de query: os 5 exemplos usam
* só model="TutorDemoPedido" + :joins pra alcançar tutor_categorias/
* tutor_estados_pedido (FK id → nome) direto no Blade.
*/
class TutorGridsPivot extends TutorPage
{
protected string $catalogKey = 'grids_pivot';
public function mount(array $params = []): void
{
TutorDemoSeed::ensure();
}
}
resources/views/tutor/grids/pivot.blade.php
<x-tutor-page page="grids_pivot">
<mad-callout type="warning" title="mad_validate acusa R045/R031 aqui — falsos positivos (schema desatualizado)" icon="alert-triangle">
O schema do <code>mad_props</code> pra <code>mad-pivot-table</code> conhece só ~13 props —
<code>name</code>, <code>joins</code>, além de <code>label</code>/<code>aggregation</code>/
<code>format</code>/<code>currency</code> em row/col/value/filter e <code>area</code> em
<code>mad-pivot-field</code>, existem de verdade (confirmado em
<code>packages/mad-framework/src/mad/views/components/pivot-table.blade.php</code> e em
<code>MadGridCompiler::buildPivotFieldAttrs</code>) mas disparam R045. O aviso R031 sobre
<code>database="business"</code> também é esperado aqui: neste projeto (mad-framework-laravel-teste)
"business" é a conexão real configurada — mesmo valor já usado no gabarito
(tutor.examples.forms-texto.db-combo). Vale reportar pra quem mantém o schema do MCP.
</mad-callout>
<x-tutor-demo demo="tutor.examples.grids-pivot.basico"
title="Básico (mad-pivot-row + mad-pivot-value)"
desc="Uma linha (categoria) e um valor agregado (soma). model + :joins resolvem a query sozinhos — zero PHP no controller." />
<x-tutor-demo demo="tutor.examples.grids-pivot.cross-tab"
title="Cross-tab (mad-pivot-row + mad-pivot-col)"
desc="Categoria nas linhas, estado do pedido nas colunas — dois joins pra trazer os dois nomes." />
<x-tutor-demo demo="tutor.examples.grids-pivot.subtotais"
title="Multi-nível com subtotais + mad-pivot-filter"
desc="Dois níveis de linha (estado > categoria) com subtotals, mais um filtro interativo por mês (SQL raw com alias)." />
<x-tutor-demo demo="tutor.examples.grids-pivot.multi-agregacao"
title="Múltiplas agregações do mesmo campo"
desc="valor_total três vezes: soma, média (ticket médio) e contagem de pedidos." />
<x-tutor-demo demo="tutor.examples.grids-pivot.campos-views"
title="Catálogo de campos + views salvas (mad-pivot-field + mad-pivot-view)"
desc="Campos declarados uma vez em mad-pivot-field; duas mad-pivot-view viram presets que o usuário troca no seletor da UI." />
</x-tutor-page>