pbStudio: Меню и страница «О нас»

- pbStudio: Создаём сайт с PageBlocks – настройка и главная страница
- pbStudio: Меню и страница «О нас»
- pbStudio: Чистый контроллер или FetchIt — два способа обработки форм
- pbStudio: Портфолио, Услуги и Контакты
- pbStudio: Подключаем мультиязычность
Настройка меню сайта
Добавляем меню на сайт.
1. Создаем ресурсы:
- О компании (about)
- Портфолио (portfolio)
- Услуги (services)
- Контакты (contacts)
2. Вывод меню в шаблоне
Добавляем код меню в чанк header (core/App/elements/chunks/header.tpl)
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand" href="{'site_url'|config}">
<img src="/assets/images/logo.svg" width="40" height="40" alt="{'site_name'|config}">
{'site_name'|config}
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar"
aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav me-auto d-flex align-items-center">
{'!pbMenu'|snippet: [
'level' => 2,
'tpl' => '@INLINE <li class="nav-item level-{$level}">
<a class="nav-link{$resourse_id === $id ? " active": ""}"
href="{$uri}" {$attributes}
>{$menutitle ?: $pagetitle}</a>
</li>'
'tplParent' => '@INLINE <li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false" {$attributes}
>{$menutitle ?: $pagetitle}</a>
<ul class="dropdown-menu">{$wrapper}</ul>
</li>'
]}
</ul>
</div>
</div>
</nav>
Страница «О нас»
Для этой страницы нам потребуется создавать 2 блока: Hero и Team
Блок Hero
Продолжаем добавлять блоки в файле core/App/Models/Resource.php1. Настройка блока.
Для этого блока нам потребуется всего лишь 2 поля — заголовок и описание.
Block::make('Hero')
->fields([
Field::make('Title')->required(),
Field::make('Description')
->type('richtext')
->required(),
]),
2. Создаем чанк core/App/elements/chunks/hero.tpl
<section class="hero my-5">
<div class="row">
<div class="col-12 col-md-4">
<h1>{$title}</h1>
</div>
<div class="col-12 pt-2 {$modx->resource->id == 2 ? 'col-md-8' : 'col-md-6 ms-auto'}">
{$description}
</div>
</div>
</section>
Блок Team

Это более сложный блок, в котором можно добавить сотрудников, текстовые описания и информацию о вакансиях.
Для реализации этого блока мы создадим зависимые поля, которые будут отображаться в зависимости от выбранного типа элемента. Всего предусмотрено три типа:
- Картинка
- Текст
- Вакансия
Если выбран тип "Картинка", отображаются поля:
- Картинка
- Имя
- Должность
- Заголовок
- Описание
- Заголовок
- Описание
- Кнопка (с текстом и ссылкой)
Block::make('Team')
->fields([
// Создаем поле таблица
Field::make('Team')
->type('table')
->fields([
// Поле выбора типа элемента
Field::make('Type')
->type('select')
->options([
'image' => 'Image',
'text' => 'Text',
'vacancy' => 'Vacancy',
])
->default('image')
->required(),
// Поля для типа "image" (сотрудник)
Field::make('Image')
->type('image')
->sourcePath('/assets/images/')
->required()
->hidden('type', '!=', 'image'),
Field::make('Name')
->width(50)
->required()
->hidden('type', '!=', 'image'),
Field::make('Position')
->width(50)
->required()
->hidden('type', '!=', 'image'),
// Поля для типов "text" и "vacancy"
Field::make('Title')
->required()
->hidden('type', '=', 'image'),
Field::make('Description')
->type('richtext')
->required()
->hidden('type', '=', 'image'),
// Поле только для вакансий
Field::make('Button')
->type('button')
->required()
->hidden('type', '!=', 'vacancy'),
])
->columns([
// Кастомная колонка, показываем картинку, а если ее нет, то заголовок
Column::make('Image')
->label('Image / Title')
->renderIf([
Column::make('Image')->render('image'),
Column::make('Title')
]),
// Группируем имя и должность
Column::make('Team')->group([
Column::make('Name'),
Column::make('Position')
])
])
]),
2. Создаем чанк core/App/elements/chunks/team.tpl
<section class="team row">
{foreach $team as $item}
{*IMAGE*}
{if $item.type === 'image'}
<div class="col-12 col-md-6 col-lg-4 mb-4">
<img
loading="lazy"
src="{$item.image.url|pthumb:'w=416&h=416&zc=T&f=webp'}"
class="img-fluid mb-2"
width="416"
height="416"
alt="{$item.name}">
<h5>{$item.name}</h5>
<p>{$item.position}</p>
</div>
{/if}
{*TEXT*}
{if $item.type === 'text'}
<div class="col-12 col-md-6 col-lg-4 mb-4">
<div class="d-flex flex-column align-item-center justify-content-center m-auto h-100 pb-5"
style="max-width: 250px">
<h2 class="mb-3">{$item.title}</h2>
{$item.description}
</div>
</div>
{/if}
{*VACANCY*}
{if $item.type === 'vacancy'}
<div class="col-12 col-md-6 col-lg-8 mb-4">
<div class="d-flex flex-column align-item-center justify-content-center m-auto h-100 pb-5"
style="max-width: 500px">
<div class="d-flex flex-column gap-3 align-items-start">
<h2>{$item.title}</h2>
{$item.description}
{$item.button|button}
</div>
</div>
</div>
{/if}
{/foreach}
</section>
Кнопка будет открывать модальное окно с формой, настройка кнопки в админке:

Для генерации кнопки на фронте используется модификатор button, который выводит готовый HTML с нужными атрибутами.
3. Модальное окно с формой
Чанк: core/App/elements/chunks/modal.tpl
<div class="modal fade" id="jobModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5">Присоединяйся к команде PageBlocks</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="/form/submit" method="post" data-pbform enctype="multipart/form-data">
<input type="hidden" name="formname" value="Job">
<input type="hidden" name="honeypot" value="">
<input type="hidden" name="_token" value="{csrf_token}">
<div class="modal-body">
<div class="mb-3">
<label for="job-name" class="col-form-label">Ваше имя:</label>
<input type="text" class="form-control" name="name" id="job-name">
<span class="invalid-feedback" data-error="name"></span>
</div>
<div class="mb-3">
<label for="job-email" class="col-form-label">E-mail:</label>
<input type="email" class="form-control" name="email" id="job-email">
<span class="invalid-feedback" data-error="email"></span>
</div>
<div class="mb-3">
<label for="job-file" class="col-form-label">Резюме (PDF, DOC, DOCX):</label>
<input type="file" class="form-control" name="file" id="job-file">
<span class="invalid-feedback" data-error="file"></span>
</div>
<div class="mb-3">
<label for="job-message" class="col-form-label">Сопроводительное письмо:</label>
<textarea class="form-control" name="message" id="job-message"></ textarea>
<span class="invalid-feedback" data-error="message"></span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
<button type="submit" class="btn btn-primary">Отправить резюме</button>
</div>
</form>
</div>
</div>
</div>
В следующей статьи мы рассмотрим обработку формы 2 способами.Все, кто дочитал до конца, ставьте лайк!
Поблагодарить автора
Отправить деньги