Pular para o conteúdo principal

Linha do Tempo

O bloco timeline-block exibe marcos cronológicos em uma seção com cabeçalho e lista de itens. No admin aparece como SGM: Linha do Tempo. Cada item tem data, subtítulo e descrição. As datas são texto livre: o PHP não parseia nem reordena os itens.

Para o guia de administração, veja Linha do Tempo.


Como foi construído

Identificação

ItemValor
ClasseSGMBlocks\Site\BlockLayout\TimelineBlock
block_layouttimeline-block
Label no adminSGM: Linha do Tempo
FormSGMBlocks\Form\TimelineBlockForm
FactorySGMBlocks\Service\BlockLayout\TimelineBlockFactory
Partialcommon/block-layout/timeline-block
JS adminasset/js/timeline-block-admin.js

Formulário estático

TimelineBlockForm define três campos de cabeçalho:

$this->add(['name' => 'o:block[__blockIndex__][o:data][subtitle]',
'type' => Element\Text::class,
'options' => ['label' => 'Subtítulo']]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][title]',
'type' => Element\Text::class,
'options' => ['label' => 'Título'],
'attributes' => ['required' => true]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][description]',
'type' => Element\Textarea::class,
'options' => ['label' => 'Descrição (opcional)'],
'attributes' => ['rows' => 3]]);

Os itens dinâmicos não entram no Fieldset. O JavaScript gera os inputs em runtime.

Classe do bloco

TimelineBlock::prepareForm anexa admin.css e timeline-block-admin.js.

TimelineBlock::form popula os três campos estáticos e concatena o gerenciador de itens com o array existente serializado em data-items:

$itemsHtml = <<<HTML
<div class="timeline-items-manager" data-items="{$itemsJson}">
<div class="field">
<div class="field-meta"><label>Itens da Linha do Tempo</label></div>
<div class="inputs">
<div class="timeline-items-container"></div>
<button type="button" class="timeline-add-item o-icon-add button">Adicionar item</button>
</div>
</div>
</div>
HTML;

Cada item persiste em:

o:block[__blockIndex__][o:data][items][i][date]
o:block[__blockIndex__][o:data][items][i][subtitle]
o:block[__blockIndex__][o:data][items][i][description]

O JS reindexa os índices ao remover um item (reindexItems).

TimelineBlock::render passa subtitle, title, description e items ao partial.

JavaScript do admin

O timeline-block-admin.js:

  1. data-items e monta entradas com campos Data, Subtítulo e Descrição (textarea simples, sem CKEditor).
  2. Adiciona itens vazios via Adicionar item.
  3. Remove itens e reindexa names dos inputs.
  4. Reinicializa em o:block-added.

Partial

O partial filtra itens sem date preenchida antes de renderizar:

$validItems = array_values(array_filter($items, function ($item) {
return !empty($item['date']);
}));

Se não houver itens válidos e o título estiver vazio, o partial retorna sem output.

Layout responsivo:

  • Mobile (sgm-timeline-mobile): lista vertical empilhada.
  • Tablet+ (sgm-timeline-tablet): carrossel Swiper com slidesPerView: 'auto' e freeMode: true. Swiper só inicializa em viewport min-width: 768px.

Assets carregados no frontend: style.css, vendor/swiper/swiper-bundle.min.css, vendor/swiper/swiper-bundle.min.js.

A ordem dos itens no site segue a ordem definida no admin. Não há sort automático por data.

Persistência

Chave em o:dataTipoObservação
subtitlestringCabeçalho opcional
titlestringCabeçalho; required no form HTML
descriptionstringCabeçalho opcional
itemsarrayLista de { date, subtitle, description }

Como usar como desenvolvedor

Sobrescrever o partial no tema

Copie view/common/block-layout/timeline-block.phtml para o tema. O Swiper e o script inline de breakpoint vêm junto.

Validar itens no render

Hoje só itens com date não vazia entram em $validItems. Para exigir subtítulo ou descrição, ajuste o filtro no partial.

Ordenar por data

O bloco não ordena. Se precisar de ordem cronológica automática, parse date no render ou no partial antes do loop. O admin grava strings como "2020", "Março de 2021" ou "15/03/2022" sem validação.

Ler o bloco em outros templates

foreach ($page->blocks() as $block) {
if ($block->layout() === 'timeline-block') {
$items = $block->dataValue('items') ?: [];
$title = $block->dataValue('title');
}
}

Depurar

  • Bloco vazio no site: confirme que pelo menos um item tem date ou que title está preenchido.
  • Carrossel não aparece: Swiper só ativa a partir de 768px; abaixo disso usa layout mobile.
  • Itens somem após salvar: item sem date é filtrado no partial.

Observações

  • Datas como rótulo. O campo Data é texto exibido tal qual. Não há date picker nem ordenação automática.
  • Mesmo padrão do acordeão. Fieldset estático + gerenciador JS + reindexação ao remover.
  • Swiper no partial. A inicialização fica inline no partial, não em asset separado do frontend.
  • Item sem data não renderiza. Mesmo com subtítulo ou descrição preenchidos, o item é ignorado se date estiver vazio.