Módulos visuais
mad-gantt-chart
mad-gantt-column
mad-gantt-toolbar
Cronograma (dados do banco)
mad-gantt declarativo lendo a fixture TutorGanttTarefa — colunas via mad-gantt-column, texto livre via mad-gantt-toolbar e hierarquia (parent-field) com caminho crítico.
Workload
resources/views/tutor/examples/modulos-gantt/declarativo.blade.php
{{--
Reabre o host — mesmo motivo do board do Kanban (escopo isolado do
x-tutor-demo). O compiler do gantt também emite "$that ?? null". Ver a
nota completa sobre as duas armadilhas de compilador regex (tag literal
em QUALQUER comentário, Blade ou PHP + nome da diretiva de bloco PHP
inline citado por extenso em qualquer comentário) em
examples/modulos-kanban/board.blade.php.
--}}
@php
$that = \Mad\Component\MadRenderContext::getComponent();
@endphp
<mad-gantt model="TutorGanttTarefa" database="business"
name-field="nome" start-field="dt_inicio" end-field="dt_fim"
parent-field="parent_id" progress-field="percentual" color-field="cor"
owner-field="responsavel" order-by="ordem"
title="Cronograma de exemplo" start-date="2026-08-24" interval="30 days"
zoom="day" critical-path striped-rows>
<mad-gantt-toolbar>
<span style="font-size:12px; color:var(--mad-text-muted);">
Arraste as barras para reagendar — a duração é salva em `dt_inicio`/`dt_fim`.
</span>
</mad-gantt-toolbar>
<mad-gantt-column field="name" label="Tarefa" width="220" tree />
<mad-gantt-column field="start" label="Início" width="100" format="date" />
<mad-gantt-column field="end" label="Fim" width="100" format="date" />
<mad-gantt-column field="duration" label="Dias" width="70" format="days" align="center" />
<mad-gantt-column field="owner" label="Resp." width="90" />
<mad-gantt-column field="progress" label="Prog." width="80" format="percent" align="right" />
</mad-gantt>
API programática (builder)
MadGantt::make(...) montado em PHP e renderizado via mad-gantt :chart — mesmo padrão do harness GanttDevView, útil quando os dados não vêm direto de uma tabela.
Workload
resources/views/tutor/examples/modulos-gantt/programatico.blade.php
@php
// Modo "chart" (:chart=) do compiler ignora config do host e só chama
// ->render() no builder devolvido — funciona mesmo sem reabrir $that,
// mas reabrimos por padronização e porque $that->chartSimples() abaixo
// precisa mesmo do host correto (TutorModulosGantt::chartSimples()).
$that = \Mad\Component\MadRenderContext::getComponent();
@endphp
<mad-gantt :chart="$that->chartSimples()" />
Código-fonte completo da página
app/control/Tutor/TutorModulosGantt.php
<?php
namespace App\Control\Tutor;
use App\Models\TutorDemo\TutorGanttTarefa;
use App\Support\Tutor\TutorCatalog;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Mad\Calendar\MadGantt;
use Mad\Calendar\MadGanttComponent;
/**
* TutorModulosGantt — página "Gantt" do MAD Lab (LOTE L9 / Onda 1).
*
* Estende Mad\Calendar\MadGanttComponent (base declarativa/auto-query do
* módulo — analoga a MadKanban/MadCalendarComponent) para o demo GRANDE:
* `<mad-gantt model=… database=…>` com `<mad-gantt-column>` e
* `<mad-gantt-toolbar>` — as 3 tags do catálogo (mad-gantt-chart,
* mad-gantt-column, mad-gantt-toolbar; "mad-gantt-chart" no catálogo é o
* nome genérico da tag real `<mad-gantt>`).
*
* O demo PEQUENO usa o modo "legado"/programático (molde: app/control/Sys/
* GanttDevView.php) — `<mad-gantt :chart="$that->chartSimples()" />` — que
* ignora toda config do host e só chama `->render()` no builder MadGantt
* devolvido pelo método. Os dois modos convivem na mesma página sem
* conflito: o modo chart não lê nem grava props do host (diferente do modo
* declarativo do Kanban), então não há o problema de "última config vence"
* documentado em TutorModulosKanban.
*/
class TutorModulosGantt extends MadGanttComponent
{
protected static string $wrapper = self::INTERNAL;
protected string $catalogKey = 'modulos_gantt';
protected string $model = 'TutorGanttTarefa';
protected string $database = 'business';
protected string $nameField = 'nome';
protected string $startField = 'dt_inicio';
protected string $endField = 'dt_fim';
protected string $parentField = 'parent_id';
protected string $progressField = 'percentual';
protected string $colorField = 'cor';
protected string $ownerField = 'responsavel';
protected string $orderBy = 'ordem';
protected string $ganttTitle = 'Cronograma de exemplo';
protected string $startDate = '2026-08-24';
protected string $interval = '30 days';
protected string $zoom = 'day';
protected bool $criticalPath = true;
public function mount(array $params = []): void
{
$this->ensureFixture();
parent::mount($params);
}
protected function view(): string|array
{
return TutorCatalog::page($this->catalogKey)['view'];
}
/**
* Demo pequeno — API programática (molde: GanttDevView::chartA()).
* Instância independente do host: não mexe em $this->model/columns/etc.
*/
public function chartSimples(): MadGantt
{
$g = MadGantt::make('2026-08-24')
->title('Sprint curto (API programática)')
->zoom('day')
->interval('14 days')
->columns([
['field' => 'name', 'label' => 'Tarefa', 'width' => 200, 'tree' => true],
['field' => 'start', 'label' => 'Início', 'width' => 90, 'format' => 'date'],
['field' => 'end', 'label' => 'Fim', 'width' => 90, 'format' => 'date'],
['field' => 'progress', 'label' => 'Prog.', 'width' => 70, 'format' => 'percent', 'align' => 'right'],
]);
$g->addTask('s1', ['name' => 'Planejamento', 'start' => '2026-08-24', 'end' => '2026-08-26', 'progress' => 1]);
$g->addTask('s2', ['name' => 'Desenvolvimento', 'start' => '2026-08-26', 'end' => '2026-09-02', 'progress' => 0.4]);
$g->addTask('s3', ['name' => 'Homologação', 'start' => '2026-09-02', 'end' => '2026-09-05', 'progress' => 0]);
$g->addTask('s4', ['name' => 'Entrega', 'type' => 'milestone', 'date' => '2026-09-05']);
$g->addDependency('s1', 's2', 'FS');
$g->addDependency('s2', 's3', 'FS');
$g->addDependency('s3', 's4', 'FS');
return $g;
}
// ── Fixture (molde: KanbanDevView::ensureFixture) ───────────────────────
private function ensureFixture(): void
{
$schema = Schema::connection('business');
if (!$schema->hasTable('tutor_gantt_tarefas')) {
$schema->create('tutor_gantt_tarefas', function ($t) {
$t->increments('id');
$t->string('nome');
$t->string('dt_inicio', 10);
$t->string('dt_fim', 10);
$t->unsignedInteger('parent_id')->nullable();
$t->decimal('percentual', 5, 2)->default(0);
$t->string('cor', 16)->nullable();
$t->string('responsavel')->nullable();
$t->integer('ordem');
});
}
if (TutorGanttTarefa::query()->count() > 0) {
return;
}
DB::connection('business')->table('tutor_gantt_tarefas')->insert([
['id' => 1, 'nome' => 'Fase 1 — Descoberta', 'dt_inicio' => '2026-08-24', 'dt_fim' => '2026-08-31', 'parent_id' => null, 'percentual' => 100, 'cor' => '#3b82f6', 'responsavel' => 'Ana', 'ordem' => 1],
['id' => 2, 'nome' => 'Entrevistas', 'dt_inicio' => '2026-08-24', 'dt_fim' => '2026-08-27', 'parent_id' => 1, 'percentual' => 100, 'cor' => '#3b82f6', 'responsavel' => 'Ana', 'ordem' => 2],
['id' => 3, 'nome' => 'Relatório', 'dt_inicio' => '2026-08-27', 'dt_fim' => '2026-08-31', 'parent_id' => 1, 'percentual' => 80, 'cor' => '#3b82f6', 'responsavel' => 'Bruno', 'ordem' => 3],
['id' => 4, 'nome' => 'Fase 2 — Construção', 'dt_inicio' => '2026-08-31', 'dt_fim' => '2026-09-14', 'parent_id' => null, 'percentual' => 35, 'cor' => '#f59e0b', 'responsavel' => 'Carla', 'ordem' => 4],
['id' => 5, 'nome' => 'Back-end', 'dt_inicio' => '2026-08-31', 'dt_fim' => '2026-09-09', 'parent_id' => 4, 'percentual' => 50, 'cor' => '#f59e0b', 'responsavel' => 'Diego', 'ordem' => 5],
['id' => 6, 'nome' => 'Front-end', 'dt_inicio' => '2026-09-03', 'dt_fim' => '2026-09-14', 'parent_id' => 4, 'percentual' => 20, 'cor' => '#f59e0b', 'responsavel' => 'Carla', 'ordem' => 6],
['id' => 7, 'nome' => 'Fase 3 — Entrega', 'dt_inicio' => '2026-09-14', 'dt_fim' => '2026-09-21', 'parent_id' => null, 'percentual' => 0, 'cor' => '#16a34a', 'responsavel' => 'Elaine', 'ordem' => 7],
['id' => 8, 'nome' => 'Homologação', 'dt_inicio' => '2026-09-14', 'dt_fim' => '2026-09-18', 'parent_id' => 7, 'percentual' => 0, 'cor' => '#16a34a', 'responsavel' => 'Elaine', 'ordem' => 8],
['id' => 9, 'nome' => 'Go-live', 'dt_inicio' => '2026-09-21', 'dt_fim' => '2026-09-21', 'parent_id' => 7, 'percentual' => 0, 'cor' => '#16a34a', 'responsavel' => 'Elaine', 'ordem' => 9],
]);
}
}
resources/views/tutor/modulos/gantt.blade.php
<x-tutor-page page="modulos_gantt">
<x-tutor-demo demo="tutor.examples.modulos-gantt.declarativo"
title="Cronograma (dados do banco)" desc="mad-gantt declarativo lendo a fixture TutorGanttTarefa — colunas via mad-gantt-column, texto livre via mad-gantt-toolbar e hierarquia (parent-field) com caminho crítico." />
<x-tutor-demo demo="tutor.examples.modulos-gantt.programatico"
title="API programática (builder)" desc="MadGantt::make(...) montado em PHP e renderizado via mad-gantt :chart — mesmo padrão do harness GanttDevView, útil quando os dados não vêm direto de uma tabela." />
</x-tutor-page>