3842 lines
122 KiB
Markdown
3842 lines
122 KiB
Markdown
# Экспертный портал БИТ.WMS — План реализации
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** Создать экспертный контентный портал по складской логистике на WordPress с фокусом на лидогенерацию для компании "Первый Бит".
|
||
|
||
**Architecture:** WordPress 6.x + GeneratePress Premium (дочерняя тема) + GenerateBlocks Pro. Контент управляется через CPT + ACF Pro. Фиксированная боковая навигация (как place.lemma.ru), строгое соответствие брендбуку "Первый Бит" (розовый/чёрный/белый, Suisse Int'l). Лидогенерация: формы Contact Form 7, JivoSite, callback, попапы, gated-контент.
|
||
|
||
**Tech Stack:** WordPress 6.x, GeneratePress Premium, GenerateBlocks Pro, ACF Pro, Contact Form 7, Popup Maker, Yoast SEO, PHP 8.x, MySQL, CSS3, vanilla JS.
|
||
|
||
**Спецификация:** `docs/superpowers/specs/2026-04-03-bit-wms-site-design.md`
|
||
|
||
---
|
||
|
||
## Файловая структура проекта
|
||
|
||
```
|
||
wp-content/
|
||
├── themes/
|
||
│ └── bitwms-child/ # Дочерняя тема GeneratePress
|
||
│ ├── style.css # Мета + кастомные стили брендбука
|
||
│ ├── functions.php # Подключение модулей
|
||
│ ├── inc/
|
||
│ │ ├── cpt.php # Регистрация кастомных типов записей
|
||
│ │ ├── acf-fields.php # ACF-группы полей (экспорт PHP)
|
||
│ │ ├── ajax-filter.php # AJAX-фильтрация ленты на главной
|
||
│ │ └── enqueue.php # Подключение шрифтов, скриптов
|
||
│ ├── templates/
|
||
│ │ ├── sidebar-nav.php # Фиксированная боковая панель
|
||
│ │ ├── hero.php # Герой главной страницы
|
||
│ │ ├── content-card.php # Карточка контента (универсальная)
|
||
│ │ ├── section-filter.php # Блок фильтрации по рубрикам
|
||
│ │ ├── section-promo-wms.php # Промо-блок БИТ.WMS
|
||
│ │ ├── section-subscribe.php # Блок подписки на рассылку
|
||
│ │ └── section-clients.php # Блок "Наши клиенты"
|
||
│ ├── template-parts/
|
||
│ │ ├── single-case.php # Детальная страница кейса
|
||
│ │ ├── single-webinar.php # Детальная страница вебинара
|
||
│ │ ├── single-course.php # Детальная страница курса
|
||
│ │ ├── single-event.php # Детальная страница мероприятия
|
||
│ │ └── single-material.php # Детальная страница материала
|
||
│ ├── page-templates/
|
||
│ │ ├── front-page.php # Шаблон главной страницы
|
||
│ │ ├── page-bit-wms.php # Шаблон страницы БИТ.WMS
|
||
│ │ ├── page-contacts.php # Шаблон страницы контактов
|
||
│ │ └── page-anketa.php # Шаблон анкеты для детального запроса
|
||
│ ├── archive/
|
||
│ │ └── archive-cpt.php # Единый шаблон архива для CPT
|
||
│ ├── js/
|
||
│ │ ├── sidebar-nav.js # Логика боковой панели (hover, мобильные)
|
||
│ │ ├── ajax-filter.js # AJAX-фильтрация + "Показать ещё"
|
||
│ │ └── gated-content.js # Модальное окно gated-контента
|
||
│ ├── fonts/
|
||
│ │ ├── SuisseIntl-Bold.woff2
|
||
│ │ └── SuisseIntl-Book.woff2
|
||
│ └── img/
|
||
│ ├── logo.svg # Логотип "первыйБит"
|
||
│ ├── logo-short.svg # Сокращённый логотип для боковой панели
|
||
│ └── icons/ # SVG-иконки для навигации
|
||
│ ├── warehouse.svg
|
||
│ ├── folder.svg
|
||
│ ├── document.svg
|
||
│ ├── camera.svg
|
||
│ ├── graduation.svg
|
||
│ ├── calendar.svg
|
||
│ ├── download.svg
|
||
│ ├── bell.svg
|
||
│ └── phone.svg
|
||
```
|
||
|
||
---
|
||
|
||
## Task 1: Установка WordPress и базовая настройка
|
||
|
||
**Контекст:** Поднимаем локальную среду разработки, устанавливаем WordPress и необходимые плагины. Это фундамент для всей последующей работы.
|
||
|
||
**Файлы:**
|
||
- Создать: конфигурация локальной среды (Local by Flywheel / Docker / MAMP)
|
||
|
||
- [ ] **Step 1: Установить WordPress локально**
|
||
|
||
Используем Local by Flywheel (рекомендуется для простоты) или Docker. Создаём сайт:
|
||
- Имя сайта: `bitwms-local`
|
||
- PHP: 8.2
|
||
- Web Server: nginx
|
||
- MySQL: 8.0
|
||
|
||
```bash
|
||
# Если используем wp-cli с уже установленным WordPress:
|
||
wp core download --locale=ru_RU
|
||
wp config create --dbname=bitwms --dbuser=root --dbpass=root --locale=ru_RU
|
||
wp db create
|
||
wp core install --url="http://bitwms.local" --title="БИТ.WMS — Экспертный портал" --admin_user=admin --admin_password=admin --admin_email=admin@bitwms.local
|
||
```
|
||
|
||
- [ ] **Step 2: Установить и активировать обязательные плагины**
|
||
|
||
```bash
|
||
# Премиум-плагины устанавливаются вручную (загрузка zip через админку):
|
||
# - GeneratePress Premium (лицензия)
|
||
# - GenerateBlocks Pro (лицензия)
|
||
# - ACF Pro (лицензия)
|
||
|
||
# Бесплатные плагины через wp-cli:
|
||
wp plugin install generatepress --activate
|
||
wp plugin install contact-form-7 --activate
|
||
wp plugin install popup-maker --activate
|
||
wp plugin install wordpress-seo --activate
|
||
|
||
# Удалить дефолтные плагины:
|
||
wp plugin delete akismet hello
|
||
```
|
||
|
||
- [ ] **Step 3: Базовые настройки WordPress**
|
||
|
||
```bash
|
||
# Постоянные ссылки: /%postname%/
|
||
wp rewrite structure '/%postname%/'
|
||
|
||
# Часовой пояс, формат дат
|
||
wp option update timezone_string 'Asia/Yekaterinburg'
|
||
wp option update date_format 'd.m.Y'
|
||
wp option update time_format 'H:i'
|
||
|
||
# Отключить комментарии
|
||
wp option update default_comment_status 'closed'
|
||
wp option update default_ping_status 'closed'
|
||
|
||
# Удалить дефолтный контент
|
||
wp post delete 1 --force
|
||
wp post delete 2 --force
|
||
wp post delete 3 --force
|
||
|
||
# Настройки чтения: статическая главная страница
|
||
wp post create --post_type=page --post_title='Главная' --post_status=publish
|
||
wp post create --post_type=page --post_title='Блог' --post_status=publish
|
||
wp option update show_on_front 'page'
|
||
wp option update page_on_front $(wp post list --post_type=page --name=главная --field=ID)
|
||
wp option update page_for_posts $(wp post list --post_type=page --name=блог --field=ID)
|
||
```
|
||
|
||
- [ ] **Step 4: Активировать GeneratePress Premium модули**
|
||
|
||
В админке WordPress: Appearance > GeneratePress > активировать модули:
|
||
- Typography
|
||
- Colors
|
||
- Spacing
|
||
- Blog
|
||
- Elements
|
||
- WooCommerce (не нужен, оставить выкл.)
|
||
- Menu Plus
|
||
- Sections (не нужен при использовании GenerateBlocks)
|
||
- Disable Elements
|
||
- Copyright
|
||
- Background Images
|
||
|
||
- [ ] **Step 5: Проверить что всё работает**
|
||
|
||
Открыть `http://bitwms.local` — должен отобразиться чистый сайт GeneratePress с русской локалью, статической главной страницей.
|
||
|
||
- [ ] **Step 6: Инициализировать git-репозиторий**
|
||
|
||
```bash
|
||
cd /path/to/wordpress/wp-content
|
||
git init
|
||
cat > .gitignore << 'EOF'
|
||
# WordPress core — не трекаем
|
||
../../*.php
|
||
../../wp-admin/
|
||
../../wp-includes/
|
||
|
||
# Плагины — премиум устанавливаются отдельно
|
||
plugins/
|
||
|
||
# Загрузки
|
||
uploads/
|
||
|
||
# Системное
|
||
.DS_Store
|
||
Thumbs.db
|
||
*.log
|
||
|
||
# Трекаем только дочернюю тему
|
||
!themes/bitwms-child/
|
||
EOF
|
||
|
||
git add .
|
||
git commit -m "init: WordPress project structure"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: Дочерняя тема — создание и подключение шрифтов
|
||
|
||
**Контекст:** Создаём дочернюю тему GeneratePress с брендбуком "Первый Бит". Шрифт Suisse Int'l — коммерческий, файлы woff2 должны быть предоставлены (или временно используем Arial как fallback).
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/style.css`
|
||
- Создать: `wp-content/themes/bitwms-child/functions.php`
|
||
- Создать: `wp-content/themes/bitwms-child/inc/enqueue.php`
|
||
|
||
- [ ] **Step 1: Создать дочернюю тему**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/style.css`:
|
||
|
||
```css
|
||
/*
|
||
Theme Name: БИТ.WMS Portal
|
||
Theme URI: https://wms.ru
|
||
Description: Дочерняя тема GeneratePress для экспертного портала БИТ.WMS
|
||
Author: Первый Бит
|
||
Author URI: https://1bit.ru
|
||
Template: generatepress
|
||
Version: 1.0.0
|
||
Text Domain: bitwms
|
||
*/
|
||
|
||
/* ==========================================================================
|
||
Брендбук "Первый Бит" — CSS Custom Properties
|
||
========================================================================== */
|
||
|
||
:root {
|
||
/* Цвета */
|
||
--color-primary: #E50071; /* Розовый/маджента — Pantone 213 */
|
||
--color-black: #000000; /* Заголовки, текст */
|
||
--color-white: #FFFFFF; /* Основной фон */
|
||
--color-gray-light: #EBEBEB; /* Дополнительный */
|
||
--color-gray-text: #666666; /* Мета-текст */
|
||
|
||
/* Типографика */
|
||
--font-heading: 'Suisse Intl', Arial, sans-serif;
|
||
--font-body: 'Suisse Intl', Arial, sans-serif;
|
||
|
||
/* Лейаут */
|
||
--sidebar-width-collapsed: 70px;
|
||
--sidebar-width-expanded: 250px;
|
||
--content-max-width: 1200px;
|
||
--header-height: 60px;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
@font-face — Suisse Int'l (файлы в fonts/)
|
||
Если шрифты недоступны, fallback на Arial (по брендбуку)
|
||
========================================================================== */
|
||
|
||
@font-face {
|
||
font-family: 'Suisse Intl';
|
||
src: url('./fonts/SuisseIntl-Bold.woff2') format('woff2');
|
||
font-weight: 700;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
@font-face {
|
||
font-family: 'Suisse Intl';
|
||
src: url('./fonts/SuisseIntl-Book.woff2') format('woff2');
|
||
font-weight: 400;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Глобальные стили
|
||
========================================================================== */
|
||
|
||
body {
|
||
font-family: var(--font-body);
|
||
font-weight: 400;
|
||
color: var(--color-black);
|
||
background-color: var(--color-white);
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
h1, h2, h3, h4, h5, h6 {
|
||
font-family: var(--font-heading);
|
||
font-weight: 700;
|
||
color: var(--color-black);
|
||
line-height: 1.2;
|
||
}
|
||
|
||
h1 { font-size: 3rem; }
|
||
h2 { font-size: 2.25rem; }
|
||
h3 { font-size: 1.5rem; }
|
||
h4 { font-size: 1.25rem; }
|
||
|
||
a {
|
||
color: var(--color-primary);
|
||
text-decoration: none;
|
||
}
|
||
|
||
a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Кнопки
|
||
========================================================================== */
|
||
|
||
.btn {
|
||
display: inline-block;
|
||
padding: 12px 32px;
|
||
font-family: var(--font-heading);
|
||
font-weight: 700;
|
||
font-size: 1rem;
|
||
line-height: 1.5;
|
||
text-decoration: none;
|
||
border-radius: 0;
|
||
cursor: pointer;
|
||
transition: background-color 0.2s, color 0.2s;
|
||
border: 2px solid transparent;
|
||
}
|
||
|
||
.btn-primary {
|
||
background-color: var(--color-primary);
|
||
color: var(--color-white);
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background-color: #C60060;
|
||
border-color: #C60060;
|
||
text-decoration: none;
|
||
color: var(--color-white);
|
||
}
|
||
|
||
.btn-outline {
|
||
background-color: transparent;
|
||
color: var(--color-black);
|
||
border-color: var(--color-black);
|
||
}
|
||
|
||
.btn-outline:hover {
|
||
background-color: var(--color-black);
|
||
color: var(--color-white);
|
||
text-decoration: none;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Утилиты
|
||
========================================================================== */
|
||
|
||
.container {
|
||
max-width: var(--content-max-width);
|
||
margin: 0 auto;
|
||
padding: 0 24px;
|
||
}
|
||
|
||
.badge {
|
||
display: inline-block;
|
||
padding: 4px 12px;
|
||
font-size: 0.75rem;
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
background-color: var(--color-gray-light);
|
||
color: var(--color-black);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Создать functions.php дочерней темы**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/functions.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* БИТ.WMS Portal — дочерняя тема GeneratePress
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
// Подключение стилей родительской темы
|
||
add_action('wp_enqueue_scripts', function () {
|
||
wp_enqueue_style(
|
||
'generatepress-parent',
|
||
get_template_directory_uri() . '/style.css'
|
||
);
|
||
wp_enqueue_style(
|
||
'bitwms-child',
|
||
get_stylesheet_uri(),
|
||
['generatepress-parent'],
|
||
wp_get_theme()->get('Version')
|
||
);
|
||
});
|
||
|
||
// Подключение модулей
|
||
$bitwms_includes = [
|
||
'inc/enqueue.php',
|
||
];
|
||
|
||
foreach ($bitwms_includes as $file) {
|
||
$filepath = get_stylesheet_directory() . '/' . $file;
|
||
if (file_exists($filepath)) {
|
||
require_once $filepath;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Создать inc/enqueue.php**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/inc/enqueue.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Подключение скриптов и стилей
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
add_action('wp_enqueue_scripts', function () {
|
||
$theme_version = wp_get_theme()->get('Version');
|
||
$theme_uri = get_stylesheet_directory_uri();
|
||
|
||
// Боковая навигация
|
||
wp_enqueue_script(
|
||
'bitwms-sidebar-nav',
|
||
$theme_uri . '/js/sidebar-nav.js',
|
||
[],
|
||
$theme_version,
|
||
true
|
||
);
|
||
}, 20);
|
||
```
|
||
|
||
- [ ] **Step 4: Создать placeholder для JS боковой навигации**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/js/sidebar-nav.js`:
|
||
|
||
```javascript
|
||
/**
|
||
* Боковая навигация — hover-раскрытие и мобильный гамбургер
|
||
*/
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const sidebar = document.querySelector('.sidebar-nav');
|
||
const hamburger = document.querySelector('.hamburger-toggle');
|
||
const body = document.body;
|
||
|
||
if (!sidebar) return;
|
||
|
||
// Мобильное меню — toggle
|
||
if (hamburger) {
|
||
hamburger.addEventListener('click', function () {
|
||
sidebar.classList.toggle('sidebar-nav--open');
|
||
body.classList.toggle('sidebar-overlay');
|
||
});
|
||
}
|
||
|
||
// Закрытие по клику на оверлей
|
||
body.addEventListener('click', function (e) {
|
||
if (e.target === body && body.classList.contains('sidebar-overlay')) {
|
||
sidebar.classList.remove('sidebar-nav--open');
|
||
body.classList.remove('sidebar-overlay');
|
||
}
|
||
});
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 5: Подготовить директории для ассетов**
|
||
|
||
```bash
|
||
cd wp-content/themes/bitwms-child
|
||
mkdir -p fonts img/icons js templates template-parts page-templates archive inc
|
||
```
|
||
|
||
Поместить шрифты Suisse Int'l (woff2) в `fonts/`. Если шрифты пока недоступны — тема будет использовать Arial как fallback (по брендбуку).
|
||
|
||
- [ ] **Step 6: Активировать дочернюю тему и проверить**
|
||
|
||
```bash
|
||
wp theme activate bitwms-child
|
||
```
|
||
|
||
Открыть `http://bitwms.local` — тема должна активироваться, стили брендбука (цвета, шрифты) должны применяться.
|
||
|
||
- [ ] **Step 7: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: create child theme with brandbook styles and fonts"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: Фиксированная боковая панель навигации
|
||
|
||
**Контекст:** Ключевой элемент лейаута — фиксированная боковая панель слева (как place.lemma.ru). В свёрнутом виде 70px с иконками, при наведении раскрывается до 250px с подписями. На мобильных — скрывается, появляется гамбургер.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/templates/sidebar-nav.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css` (добавить стили панели)
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php` (подключить шаблон)
|
||
|
||
- [ ] **Step 1: Создать SVG-иконки навигации**
|
||
|
||
Создать директорию `wp-content/themes/bitwms-child/img/icons/` и поместить туда SVG-файлы. Используем простые моноцветные иконки (чёрный, без теней и градиентов по брендбуку).
|
||
|
||
Минимальный набор SVG (можно взять из Lucide Icons или Heroicons и упростить до монохромных):
|
||
- `warehouse.svg` — БИТ.WMS
|
||
- `folder.svg` — Кейсы
|
||
- `document.svg` — Статьи
|
||
- `camera.svg` — Вебинары
|
||
- `graduation.svg` — Курсы
|
||
- `calendar.svg` — Мероприятия
|
||
- `download.svg` — Материалы
|
||
- `bell.svg` — Новости
|
||
- `phone.svg` — Контакты
|
||
- `telegram.svg` — Telegram
|
||
- `vk.svg` — VK
|
||
|
||
- [ ] **Step 2: Создать шаблон боковой панели**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/sidebar-nav.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Фиксированная боковая панель навигации
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
$theme_uri = get_stylesheet_directory_uri();
|
||
|
||
$nav_items = [
|
||
[
|
||
'label' => 'БИТ.WMS',
|
||
'icon' => 'warehouse.svg',
|
||
'url' => '/bit-wms/',
|
||
],
|
||
[
|
||
'label' => 'Кейсы',
|
||
'icon' => 'folder.svg',
|
||
'url' => '/cases/',
|
||
],
|
||
[
|
||
'label' => 'Статьи',
|
||
'icon' => 'document.svg',
|
||
'url' => '/articles/',
|
||
],
|
||
[
|
||
'label' => 'Вебинары',
|
||
'icon' => 'camera.svg',
|
||
'url' => '/webinars/',
|
||
],
|
||
[
|
||
'label' => 'Курсы',
|
||
'icon' => 'graduation.svg',
|
||
'url' => '/courses/',
|
||
],
|
||
[
|
||
'label' => 'Мероприятия',
|
||
'icon' => 'calendar.svg',
|
||
'url' => '/events/',
|
||
],
|
||
[
|
||
'label' => 'Материалы',
|
||
'icon' => 'download.svg',
|
||
'url' => '/materials/',
|
||
],
|
||
[
|
||
'label' => 'Новости',
|
||
'icon' => 'bell.svg',
|
||
'url' => '/news/',
|
||
],
|
||
[
|
||
'label' => 'Контакты',
|
||
'icon' => 'phone.svg',
|
||
'url' => '/contacts/',
|
||
],
|
||
];
|
||
|
||
$current_path = wp_parse_url(get_permalink(), PHP_URL_PATH);
|
||
?>
|
||
|
||
<aside class="sidebar-nav" role="navigation" aria-label="Основная навигация">
|
||
<div class="sidebar-nav__logo">
|
||
<a href="<?php echo esc_url(home_url('/')); ?>">
|
||
<img src="<?php echo esc_url($theme_uri . '/img/logo-short.svg'); ?>"
|
||
alt="первыйБит"
|
||
class="sidebar-nav__logo-img" />
|
||
</a>
|
||
</div>
|
||
|
||
<nav class="sidebar-nav__menu">
|
||
<ul class="sidebar-nav__list">
|
||
<?php foreach ($nav_items as $item) :
|
||
$is_active = (strpos($current_path, $item['url']) === 0);
|
||
?>
|
||
<li class="sidebar-nav__item <?php echo $is_active ? 'sidebar-nav__item--active' : ''; ?>">
|
||
<a href="<?php echo esc_url(home_url($item['url'])); ?>"
|
||
class="sidebar-nav__link">
|
||
<span class="sidebar-nav__icon">
|
||
<img src="<?php echo esc_url($theme_uri . '/img/icons/' . $item['icon']); ?>"
|
||
alt="" aria-hidden="true" width="24" height="24" />
|
||
</span>
|
||
<span class="sidebar-nav__label"><?php echo esc_html($item['label']); ?></span>
|
||
</a>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</nav>
|
||
|
||
<div class="sidebar-nav__social">
|
||
<a href="#" class="sidebar-nav__social-link" aria-label="Telegram">
|
||
<img src="<?php echo esc_url($theme_uri . '/img/icons/telegram.svg'); ?>"
|
||
alt="" width="20" height="20" />
|
||
</a>
|
||
<a href="#" class="sidebar-nav__social-link" aria-label="VK">
|
||
<img src="<?php echo esc_url($theme_uri . '/img/icons/vk.svg'); ?>"
|
||
alt="" width="20" height="20" />
|
||
</a>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Мобильный гамбургер (виден только на <768px) -->
|
||
<button class="hamburger-toggle" aria-label="Открыть меню" aria-expanded="false">
|
||
<span class="hamburger-toggle__bar"></span>
|
||
<span class="hamburger-toggle__bar"></span>
|
||
<span class="hamburger-toggle__bar"></span>
|
||
</button>
|
||
```
|
||
|
||
- [ ] **Step 3: Добавить CSS боковой панели**
|
||
|
||
Добавить в конец `wp-content/themes/bitwms-child/style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Боковая панель навигации
|
||
========================================================================== */
|
||
|
||
.sidebar-nav {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: var(--sidebar-width-collapsed);
|
||
height: 100vh;
|
||
background-color: var(--color-white);
|
||
border-right: 1px solid var(--color-gray-light);
|
||
z-index: 1000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: width 0.25s ease;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sidebar-nav:hover {
|
||
width: var(--sidebar-width-expanded);
|
||
}
|
||
|
||
.sidebar-nav__logo {
|
||
padding: 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 60px;
|
||
border-bottom: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.sidebar-nav__logo-img {
|
||
width: 36px;
|
||
height: auto;
|
||
}
|
||
|
||
.sidebar-nav__menu {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: 16px 0;
|
||
}
|
||
|
||
.sidebar-nav__list {
|
||
list-style: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.sidebar-nav__item {
|
||
margin: 0;
|
||
}
|
||
|
||
.sidebar-nav__link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
padding: 12px 23px;
|
||
color: var(--color-black);
|
||
text-decoration: none;
|
||
font-size: 0.875rem;
|
||
font-weight: 400;
|
||
white-space: nowrap;
|
||
transition: background-color 0.15s;
|
||
}
|
||
|
||
.sidebar-nav__link:hover {
|
||
background-color: var(--color-gray-light);
|
||
text-decoration: none;
|
||
color: var(--color-black);
|
||
}
|
||
|
||
.sidebar-nav__item--active .sidebar-nav__link {
|
||
color: var(--color-primary);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.sidebar-nav__item--active .sidebar-nav__link img {
|
||
filter: brightness(0) saturate(100%) invert(12%) sepia(97%) saturate(5765%) hue-rotate(327deg) brightness(87%) contrast(107%);
|
||
}
|
||
|
||
.sidebar-nav__icon {
|
||
flex-shrink: 0;
|
||
width: 24px;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.sidebar-nav__label {
|
||
opacity: 0;
|
||
transition: opacity 0.2s ease 0.05s;
|
||
}
|
||
|
||
.sidebar-nav:hover .sidebar-nav__label {
|
||
opacity: 1;
|
||
}
|
||
|
||
.sidebar-nav__social {
|
||
padding: 16px;
|
||
display: flex;
|
||
gap: 12px;
|
||
justify-content: center;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.sidebar-nav__social-link {
|
||
opacity: 0.6;
|
||
transition: opacity 0.15s;
|
||
}
|
||
|
||
.sidebar-nav__social-link:hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Сдвиг основного контента */
|
||
.site-content,
|
||
.site-header,
|
||
.site-footer {
|
||
margin-left: var(--sidebar-width-collapsed);
|
||
}
|
||
|
||
/* Гамбургер — скрыт на десктопе */
|
||
.hamburger-toggle {
|
||
display: none;
|
||
position: fixed;
|
||
top: 16px;
|
||
left: 16px;
|
||
z-index: 1001;
|
||
background: var(--color-white);
|
||
border: 1px solid var(--color-gray-light);
|
||
padding: 8px;
|
||
cursor: pointer;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.hamburger-toggle__bar {
|
||
display: block;
|
||
width: 24px;
|
||
height: 2px;
|
||
background-color: var(--color-black);
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Мобильные стили (< 768px)
|
||
========================================================================== */
|
||
|
||
@media (max-width: 767px) {
|
||
.sidebar-nav {
|
||
transform: translateX(-100%);
|
||
width: var(--sidebar-width-expanded);
|
||
}
|
||
|
||
.sidebar-nav--open {
|
||
transform: translateX(0);
|
||
}
|
||
|
||
.sidebar-nav--open .sidebar-nav__label {
|
||
opacity: 1;
|
||
}
|
||
|
||
.hamburger-toggle {
|
||
display: flex;
|
||
}
|
||
|
||
.site-content,
|
||
.site-header,
|
||
.site-footer {
|
||
margin-left: 0;
|
||
}
|
||
|
||
body.sidebar-overlay::after {
|
||
content: '';
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(0, 0, 0, 0.4);
|
||
z-index: 999;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Подключить боковую панель в тему**
|
||
|
||
Добавить в `wp-content/themes/bitwms-child/functions.php` (перед закрывающим `?>` или в конец):
|
||
|
||
```php
|
||
// Вставка боковой панели после <body>
|
||
add_action('generate_before_header', function () {
|
||
get_template_part('templates/sidebar-nav');
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 5: Проверить боковую панель**
|
||
|
||
Открыть `http://bitwms.local`:
|
||
- На десктопе: боковая панель 70px слева с иконками, при наведении раскрывается до 250px с подписями
|
||
- На мобильном (< 768px): панель скрыта, виден гамбургер, по клику панель выезжает с оверлеем
|
||
- Основной контент сдвинут вправо на 70px
|
||
|
||
- [ ] **Step 6: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add fixed sidebar navigation with hover expand and mobile hamburger"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: Верхний хедер
|
||
|
||
**Контекст:** Тонкий хедер над основным контентом (правее боковой панели): логотип + слоган слева, телефон + CTA "Заказать демо" + поиск справа. Высота ~60px.
|
||
|
||
**Файлы:**
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php`
|
||
|
||
- [ ] **Step 1: Настроить хедер через GeneratePress hooks**
|
||
|
||
Добавить в `wp-content/themes/bitwms-child/functions.php`:
|
||
|
||
```php
|
||
// Кастомный хедер
|
||
add_action('generate_before_header', function () {
|
||
// Боковая панель уже подключена выше
|
||
}, 5);
|
||
|
||
// Переопределяем содержимое хедера
|
||
add_filter('generate_header_items_order', function () {
|
||
return ['header-widget', 'site-branding', 'navigation'];
|
||
});
|
||
```
|
||
|
||
Через Customizer GeneratePress (Appearance > Customize > Layout > Header): выбрать лейаут хедера "inline with navigation" или настроить через Elements.
|
||
|
||
Альтернативно, создать кастомный хедер через GP Elements (Appearance > Elements > Header):
|
||
|
||
```html
|
||
<div class="top-header">
|
||
<div class="top-header__left">
|
||
<a href="/" class="top-header__logo">
|
||
<img src="/wp-content/themes/bitwms-child/img/logo.svg" alt="первыйБит" height="30" />
|
||
</a>
|
||
<span class="top-header__tagline">Экспертный портал по складской логистике</span>
|
||
</div>
|
||
<div class="top-header__right">
|
||
<a href="tel:+73432000000" class="top-header__phone">+7 (343) 200-00-00</a>
|
||
<a href="#demo-form" class="btn btn-primary btn-sm" data-popup="demo">Заказать демо</a>
|
||
<button class="top-header__search" aria-label="Поиск">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
- [ ] **Step 2: Добавить CSS хедера**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Верхний хедер
|
||
========================================================================== */
|
||
|
||
.top-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: var(--header-height);
|
||
padding: 0 32px;
|
||
background-color: var(--color-white);
|
||
border-bottom: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.top-header__left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
}
|
||
|
||
.top-header__logo img {
|
||
height: 30px;
|
||
width: auto;
|
||
}
|
||
|
||
.top-header__tagline {
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.top-header__right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24px;
|
||
}
|
||
|
||
.top-header__phone {
|
||
font-weight: 700;
|
||
color: var(--color-black);
|
||
text-decoration: none;
|
||
font-size: 0.875rem;
|
||
}
|
||
|
||
.top-header__phone:hover {
|
||
color: var(--color-primary);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.btn-sm {
|
||
padding: 8px 20px;
|
||
font-size: 0.875rem;
|
||
}
|
||
|
||
.top-header__search {
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
color: var(--color-black);
|
||
padding: 4px;
|
||
}
|
||
|
||
.top-header__search:hover {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.top-header {
|
||
padding: 0 16px 0 56px; /* Отступ под гамбургер */
|
||
}
|
||
|
||
.top-header__tagline {
|
||
display: none;
|
||
}
|
||
|
||
.top-header__phone {
|
||
display: none;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Проверить хедер**
|
||
|
||
Открыть `http://bitwms.local`:
|
||
- Хедер 60px, прижат к верху, правее боковой панели
|
||
- Логотип + слоган слева, телефон + "Заказать демо" + лупа справа
|
||
- На мобильном: слоган и телефон скрыты
|
||
|
||
- [ ] **Step 4: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add top header with logo, phone and demo CTA"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 5: Регистрация кастомных типов записей (CPT)
|
||
|
||
**Контекст:** Регистрируем 5 кастомных типов записей: case, webinar, course, event, material. Статьи и Новости — стандартный post с рубриками.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/inc/cpt.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php` (подключить файл)
|
||
|
||
- [ ] **Step 1: Создать файл регистрации CPT**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/inc/cpt.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Регистрация кастомных типов записей
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
add_action('init', 'bitwms_register_post_types');
|
||
|
||
function bitwms_register_post_types(): void {
|
||
// Кейсы
|
||
register_post_type('case', [
|
||
'labels' => [
|
||
'name' => 'Кейсы',
|
||
'singular_name' => 'Кейс',
|
||
'add_new' => 'Добавить кейс',
|
||
'add_new_item' => 'Добавить новый кейс',
|
||
'edit_item' => 'Редактировать кейс',
|
||
'view_item' => 'Просмотреть кейс',
|
||
'all_items' => 'Все кейсы',
|
||
'search_items' => 'Найти кейс',
|
||
'not_found' => 'Кейсы не найдены',
|
||
'not_found_in_trash' => 'В корзине кейсов нет',
|
||
],
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'rewrite' => ['slug' => 'cases'],
|
||
'menu_icon' => 'dashicons-portfolio',
|
||
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Вебинары
|
||
register_post_type('webinar', [
|
||
'labels' => [
|
||
'name' => 'Вебинары',
|
||
'singular_name' => 'Вебинар',
|
||
'add_new' => 'Добавить вебинар',
|
||
'add_new_item' => 'Добавить новый вебинар',
|
||
'edit_item' => 'Редактировать вебинар',
|
||
'view_item' => 'Просмотреть вебинар',
|
||
'all_items' => 'Все вебинары',
|
||
'search_items' => 'Найти вебинар',
|
||
'not_found' => 'Вебинары не найдены',
|
||
'not_found_in_trash' => 'В корзине вебинаров нет',
|
||
],
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'rewrite' => ['slug' => 'webinars'],
|
||
'menu_icon' => 'dashicons-video-alt3',
|
||
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Курсы
|
||
register_post_type('course', [
|
||
'labels' => [
|
||
'name' => 'Курсы',
|
||
'singular_name' => 'Курс',
|
||
'add_new' => 'Добавить курс',
|
||
'add_new_item' => 'Добавить новый курс',
|
||
'edit_item' => 'Редактировать курс',
|
||
'view_item' => 'Просмотреть курс',
|
||
'all_items' => 'Все курсы',
|
||
'search_items' => 'Найти курс',
|
||
'not_found' => 'Курсы не найдены',
|
||
'not_found_in_trash' => 'В корзине курсов нет',
|
||
],
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'rewrite' => ['slug' => 'courses'],
|
||
'menu_icon' => 'dashicons-welcome-learn-more',
|
||
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Мероприятия
|
||
register_post_type('event', [
|
||
'labels' => [
|
||
'name' => 'Мероприятия',
|
||
'singular_name' => 'Мероприятие',
|
||
'add_new' => 'Добавить мероприятие',
|
||
'add_new_item' => 'Добавить новое мероприятие',
|
||
'edit_item' => 'Редактировать мероприятие',
|
||
'view_item' => 'Просмотреть мероприятие',
|
||
'all_items' => 'Все мероприятия',
|
||
'search_items' => 'Найти мероприятие',
|
||
'not_found' => 'Мероприятия не найдены',
|
||
'not_found_in_trash' => 'В корзине мероприятий нет',
|
||
],
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'rewrite' => ['slug' => 'events'],
|
||
'menu_icon' => 'dashicons-calendar-alt',
|
||
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Материалы
|
||
register_post_type('material', [
|
||
'labels' => [
|
||
'name' => 'Материалы',
|
||
'singular_name' => 'Материал',
|
||
'add_new' => 'Добавить материал',
|
||
'add_new_item' => 'Добавить новый материал',
|
||
'edit_item' => 'Редактировать материал',
|
||
'view_item' => 'Просмотреть материал',
|
||
'all_items' => 'Все материалы',
|
||
'search_items' => 'Найти материал',
|
||
'not_found' => 'Материалы не найдены',
|
||
'not_found_in_trash' => 'В корзине материалов нет',
|
||
],
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'rewrite' => ['slug' => 'materials'],
|
||
'menu_icon' => 'dashicons-download',
|
||
'supports' => ['title', 'thumbnail', 'excerpt'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Таксономии: Отрасли (для кейсов)
|
||
register_taxonomy('industry', ['case'], [
|
||
'labels' => [
|
||
'name' => 'Отрасли',
|
||
'singular_name' => 'Отрасль',
|
||
'add_new_item' => 'Добавить отрасль',
|
||
],
|
||
'public' => true,
|
||
'hierarchical' => true,
|
||
'rewrite' => ['slug' => 'industry'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Таксономии: Тип материала
|
||
register_taxonomy('material_type', ['material'], [
|
||
'labels' => [
|
||
'name' => 'Тип материала',
|
||
'singular_name' => 'Тип материала',
|
||
'add_new_item' => 'Добавить тип',
|
||
],
|
||
'public' => true,
|
||
'hierarchical' => true,
|
||
'rewrite' => ['slug' => 'material-type'],
|
||
'show_in_rest' => true,
|
||
]);
|
||
|
||
// Рубрики для Статей и Новостей (стандартный post)
|
||
// "Статьи" и "Новости" — рубрики, создаются в админке
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Подключить CPT в functions.php**
|
||
|
||
Добавить `'inc/cpt.php'` в массив `$bitwms_includes` в `functions.php`:
|
||
|
||
```php
|
||
$bitwms_includes = [
|
||
'inc/enqueue.php',
|
||
'inc/cpt.php',
|
||
];
|
||
```
|
||
|
||
- [ ] **Step 3: Обновить permalink и проверить**
|
||
|
||
```bash
|
||
wp rewrite flush
|
||
```
|
||
|
||
В админке WP: проверить что в меню появились разделы "Кейсы", "Вебинары", "Курсы", "Мероприятия", "Материалы".
|
||
|
||
Создать рубрики для стандартных постов:
|
||
```bash
|
||
wp term create category "Статьи" --slug=articles
|
||
wp term create category "Новости" --slug=news
|
||
```
|
||
|
||
- [ ] **Step 4: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/inc/cpt.php themes/bitwms-child/functions.php
|
||
git commit -m "feat: register custom post types (case, webinar, course, event, material)"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 6: ACF-поля для кастомных типов записей
|
||
|
||
**Контекст:** Настраиваем кастомные поля через ACF Pro для каждого CPT. Поля экспортируем в PHP для версионного контроля.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/inc/acf-fields.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php`
|
||
|
||
- [ ] **Step 1: Создать ACF-группы полей в PHP**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/inc/acf-fields.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* ACF-группы полей для кастомных типов записей
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
if (!function_exists('acf_add_local_field_group')) {
|
||
return;
|
||
}
|
||
|
||
add_action('acf/init', 'bitwms_register_acf_fields');
|
||
|
||
function bitwms_register_acf_fields(): void {
|
||
|
||
// ===== Кейсы =====
|
||
acf_add_local_field_group([
|
||
'key' => 'group_case_fields',
|
||
'title' => 'Поля кейса',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_case_client',
|
||
'label' => 'Клиент',
|
||
'name' => 'case_client',
|
||
'type' => 'text',
|
||
'required' => 1,
|
||
],
|
||
[
|
||
'key' => 'field_case_industry',
|
||
'label' => 'Отрасль',
|
||
'name' => 'case_industry',
|
||
'type' => 'text',
|
||
],
|
||
[
|
||
'key' => 'field_case_task',
|
||
'label' => 'Задача',
|
||
'name' => 'case_task',
|
||
'type' => 'wysiwyg',
|
||
'toolbar' => 'basic',
|
||
],
|
||
[
|
||
'key' => 'field_case_solution',
|
||
'label' => 'Решение',
|
||
'name' => 'case_solution',
|
||
'type' => 'wysiwyg',
|
||
'toolbar' => 'basic',
|
||
],
|
||
[
|
||
'key' => 'field_case_result',
|
||
'label' => 'Результат',
|
||
'name' => 'case_result',
|
||
'type' => 'wysiwyg',
|
||
'toolbar' => 'basic',
|
||
],
|
||
[
|
||
'key' => 'field_case_quote',
|
||
'label' => 'Цитата клиента',
|
||
'name' => 'case_quote',
|
||
'type' => 'textarea',
|
||
'rows' => 3,
|
||
],
|
||
[
|
||
'key' => 'field_case_gallery',
|
||
'label' => 'Галерея',
|
||
'name' => 'case_gallery',
|
||
'type' => 'gallery',
|
||
'return_format' => 'array',
|
||
],
|
||
],
|
||
'location' => [
|
||
[['param' => 'post_type', 'operator' => '==', 'value' => 'case']],
|
||
],
|
||
]);
|
||
|
||
// ===== Вебинары =====
|
||
acf_add_local_field_group([
|
||
'key' => 'group_webinar_fields',
|
||
'title' => 'Поля вебинара',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_webinar_date',
|
||
'label' => 'Дата проведения',
|
||
'name' => 'webinar_date',
|
||
'type' => 'date_time_picker',
|
||
'display_format' => 'd.m.Y H:i',
|
||
'return_format' => 'Y-m-d H:i:s',
|
||
'required' => 1,
|
||
],
|
||
[
|
||
'key' => 'field_webinar_speaker',
|
||
'label' => 'Спикер',
|
||
'name' => 'webinar_speaker',
|
||
'type' => 'text',
|
||
],
|
||
[
|
||
'key' => 'field_webinar_status',
|
||
'label' => 'Статус',
|
||
'name' => 'webinar_status',
|
||
'type' => 'select',
|
||
'choices' => [
|
||
'upcoming' => 'Анонс',
|
||
'past' => 'Прошёл',
|
||
],
|
||
'default_value' => 'upcoming',
|
||
],
|
||
[
|
||
'key' => 'field_webinar_video',
|
||
'label' => 'Запись видео (URL)',
|
||
'name' => 'webinar_video',
|
||
'type' => 'url',
|
||
'conditional_logic' => [
|
||
[['field' => 'field_webinar_status', 'operator' => '==', 'value' => 'past']],
|
||
],
|
||
],
|
||
[
|
||
'key' => 'field_webinar_presentation',
|
||
'label' => 'Презентация (файл)',
|
||
'name' => 'webinar_presentation',
|
||
'type' => 'file',
|
||
'return_format' => 'url',
|
||
'conditional_logic' => [
|
||
[['field' => 'field_webinar_status', 'operator' => '==', 'value' => 'past']],
|
||
],
|
||
],
|
||
],
|
||
'location' => [
|
||
[['param' => 'post_type', 'operator' => '==', 'value' => 'webinar']],
|
||
],
|
||
]);
|
||
|
||
// ===== Курсы =====
|
||
acf_add_local_field_group([
|
||
'key' => 'group_course_fields',
|
||
'title' => 'Поля курса',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_course_program',
|
||
'label' => 'Программа курса',
|
||
'name' => 'course_program',
|
||
'type' => 'wysiwyg',
|
||
'toolbar' => 'full',
|
||
],
|
||
[
|
||
'key' => 'field_course_duration',
|
||
'label' => 'Длительность',
|
||
'name' => 'course_duration',
|
||
'type' => 'text',
|
||
'placeholder' => 'Например: 2 дня (16 часов)',
|
||
],
|
||
[
|
||
'key' => 'field_course_format',
|
||
'label' => 'Формат',
|
||
'name' => 'course_format',
|
||
'type' => 'select',
|
||
'choices' => [
|
||
'online' => 'Онлайн',
|
||
'offline' => 'Очно',
|
||
'mixed' => 'Смешанный',
|
||
],
|
||
],
|
||
[
|
||
'key' => 'field_course_price',
|
||
'label' => 'Стоимость',
|
||
'name' => 'course_price',
|
||
'type' => 'text',
|
||
'placeholder' => 'Например: 25 000 руб.',
|
||
],
|
||
],
|
||
'location' => [
|
||
[['param' => 'post_type', 'operator' => '==', 'value' => 'course']],
|
||
],
|
||
]);
|
||
|
||
// ===== Мероприятия =====
|
||
acf_add_local_field_group([
|
||
'key' => 'group_event_fields',
|
||
'title' => 'Поля мероприятия',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_event_date',
|
||
'label' => 'Дата проведения',
|
||
'name' => 'event_date',
|
||
'type' => 'date_time_picker',
|
||
'display_format' => 'd.m.Y H:i',
|
||
'return_format' => 'Y-m-d H:i:s',
|
||
'required' => 1,
|
||
],
|
||
[
|
||
'key' => 'field_event_location',
|
||
'label' => 'Место проведения',
|
||
'name' => 'event_location',
|
||
'type' => 'text',
|
||
],
|
||
[
|
||
'key' => 'field_event_format',
|
||
'label' => 'Формат',
|
||
'name' => 'event_format',
|
||
'type' => 'select',
|
||
'choices' => [
|
||
'online' => 'Онлайн',
|
||
'offline' => 'Очно',
|
||
'mixed' => 'Смешанный',
|
||
],
|
||
],
|
||
[
|
||
'key' => 'field_event_program',
|
||
'label' => 'Программа',
|
||
'name' => 'event_program',
|
||
'type' => 'wysiwyg',
|
||
'toolbar' => 'basic',
|
||
],
|
||
[
|
||
'key' => 'field_event_registration_url',
|
||
'label' => 'Ссылка на регистрацию',
|
||
'name' => 'event_registration_url',
|
||
'type' => 'url',
|
||
],
|
||
],
|
||
'location' => [
|
||
[['param' => 'post_type', 'operator' => '==', 'value' => 'event']],
|
||
],
|
||
]);
|
||
|
||
// ===== Материалы =====
|
||
acf_add_local_field_group([
|
||
'key' => 'group_material_fields',
|
||
'title' => 'Поля материала',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_material_file',
|
||
'label' => 'Файл',
|
||
'name' => 'material_file',
|
||
'type' => 'file',
|
||
'return_format' => 'array',
|
||
],
|
||
[
|
||
'key' => 'field_material_type',
|
||
'label' => 'Тип файла',
|
||
'name' => 'material_file_type',
|
||
'type' => 'select',
|
||
'choices' => [
|
||
'pdf' => 'PDF',
|
||
'video' => 'Видео',
|
||
'checklist' => 'Чек-лист',
|
||
'excel' => 'Excel',
|
||
'other' => 'Другое',
|
||
],
|
||
],
|
||
[
|
||
'key' => 'field_material_gated',
|
||
'label' => 'Gated-контент (скачивание за email)',
|
||
'name' => 'material_gated',
|
||
'type' => 'true_false',
|
||
'default_value' => 0,
|
||
'ui' => 1,
|
||
],
|
||
],
|
||
'location' => [
|
||
[['param' => 'post_type', 'operator' => '==', 'value' => 'material']],
|
||
],
|
||
]);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Подключить ACF-поля в functions.php**
|
||
|
||
Добавить `'inc/acf-fields.php'` в массив `$bitwms_includes`:
|
||
|
||
```php
|
||
$bitwms_includes = [
|
||
'inc/enqueue.php',
|
||
'inc/cpt.php',
|
||
'inc/acf-fields.php',
|
||
];
|
||
```
|
||
|
||
- [ ] **Step 3: Проверить поля в админке**
|
||
|
||
В админке WP: открыть создание нового Кейса, Вебинара, Курса, Мероприятия, Материала — проверить что все ACF-поля отображаются корректно с нужными типами и условной логикой (например, "Запись видео" появляется только при статусе "Прошёл").
|
||
|
||
- [ ] **Step 4: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/inc/acf-fields.php themes/bitwms-child/functions.php
|
||
git commit -m "feat: add ACF field groups for all custom post types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 7: Главная страница — шаблон и герой
|
||
|
||
**Контекст:** Шаблон главной страницы: герой + фильтр по рубрикам + лента контента + промо WMS + подписка + клиенты. Начинаем с героя.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/page-templates/front-page.php`
|
||
- Создать: `wp-content/themes/bitwms-child/templates/hero.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
|
||
- [ ] **Step 1: Создать шаблон главной страницы**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/page-templates/front-page.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Template Name: Главная страница
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header();
|
||
?>
|
||
|
||
<main class="front-page">
|
||
<?php get_template_part('templates/hero'); ?>
|
||
<?php get_template_part('templates/section-filter'); ?>
|
||
<?php // Лента контента будет добавлена в Task 9 ?>
|
||
<?php get_template_part('templates/section-promo-wms'); ?>
|
||
<?php get_template_part('templates/section-subscribe'); ?>
|
||
<?php get_template_part('templates/section-clients'); ?>
|
||
</main>
|
||
|
||
<?php
|
||
get_footer();
|
||
```
|
||
|
||
- [ ] **Step 2: Создать шаблон героя**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/hero.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Герой главной страницы
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
?>
|
||
|
||
<section class="hero">
|
||
<div class="container">
|
||
<div class="hero__content">
|
||
<h1 class="hero__title">Всё о складской логистике и автоматизации склада</h1>
|
||
<p class="hero__subtitle">Экспертный портал от Первого Бита — кейсы, вебинары, курсы и материалы для руководителей складов</p>
|
||
<div class="hero__actions">
|
||
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-primary">Заказать демо БИТ.WMS</a>
|
||
<a href="<?php echo esc_url(home_url('/cases/')); ?>" class="btn btn-outline">Смотреть кейсы</a>
|
||
</div>
|
||
</div>
|
||
<div class="hero__stats">
|
||
<div class="hero__stat">
|
||
<span class="hero__stat-number">200+</span>
|
||
<span class="hero__stat-label">проектов внедрения</span>
|
||
</div>
|
||
<div class="hero__stat">
|
||
<span class="hero__stat-number">15+</span>
|
||
<span class="hero__stat-label">лет опыта в WMS</span>
|
||
</div>
|
||
<div class="hero__stat">
|
||
<span class="hero__stat-number">50+</span>
|
||
<span class="hero__stat-label">экспертов в команде</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
```
|
||
|
||
- [ ] **Step 3: Добавить CSS героя**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Герой главной страницы
|
||
========================================================================== */
|
||
|
||
.hero {
|
||
padding: 80px 0 60px;
|
||
}
|
||
|
||
.hero__title {
|
||
font-size: 3.5rem;
|
||
line-height: 1.1;
|
||
margin: 0 0 24px;
|
||
max-width: 700px;
|
||
}
|
||
|
||
.hero__subtitle {
|
||
font-size: 1.25rem;
|
||
line-height: 1.6;
|
||
color: var(--color-gray-text);
|
||
margin: 0 0 40px;
|
||
max-width: 600px;
|
||
}
|
||
|
||
.hero__actions {
|
||
display: flex;
|
||
gap: 16px;
|
||
margin-bottom: 60px;
|
||
}
|
||
|
||
.hero__stats {
|
||
display: flex;
|
||
gap: 48px;
|
||
}
|
||
|
||
.hero__stat {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.hero__stat-number {
|
||
font-family: var(--font-heading);
|
||
font-weight: 700;
|
||
font-size: 2.5rem;
|
||
line-height: 1;
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.hero__stat-label {
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.hero {
|
||
padding: 40px 0 32px;
|
||
}
|
||
|
||
.hero__title {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.hero__subtitle {
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.hero__actions {
|
||
flex-direction: column;
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.hero__stats {
|
||
flex-direction: column;
|
||
gap: 24px;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Назначить шаблон странице "Главная" в админке**
|
||
|
||
В админке WP: Страницы > Главная > в блоке "Атрибуты страницы" выбрать шаблон "Главная страница".
|
||
|
||
Альтернативно — переименовать файл в `front-page.php` (без Template Name) и положить в корень дочерней темы, тогда WordPress подхватит его автоматически для статической главной.
|
||
|
||
- [ ] **Step 5: Проверить главную**
|
||
|
||
Открыть `http://bitwms.local`:
|
||
- Герой с H1, подзаголовком, двумя кнопками, тремя KPI-цифрами
|
||
- Типографика Suisse Int'l / Arial, цвета по брендбуку
|
||
- Адаптивность на мобильном
|
||
|
||
- [ ] **Step 6: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add front page template with hero section"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 8: Главная — промо-блок WMS, подписка, клиенты
|
||
|
||
**Контекст:** Оставшиеся блоки главной страницы: промо БИТ.WMS, подписка на рассылку, логотипы клиентов.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/templates/section-promo-wms.php`
|
||
- Создать: `wp-content/themes/bitwms-child/templates/section-subscribe.php`
|
||
- Создать: `wp-content/themes/bitwms-child/templates/section-clients.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
|
||
- [ ] **Step 1: Создать промо-блок БИТ.WMS**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/section-promo-wms.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Промо-блок БИТ.WMS на главной
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
?>
|
||
|
||
<section class="promo-wms">
|
||
<div class="container">
|
||
<h2 class="promo-wms__title">БИТ.WMS — комплексное решение для вашего склада</h2>
|
||
<div class="promo-wms__grid">
|
||
<div class="promo-wms__item">
|
||
<span class="promo-wms__icon">⚡</span>
|
||
<h3>Быстрое внедрение</h3>
|
||
<p>Знаем бизнес-задачи склада, запускаем проект за недели, а не месяцы</p>
|
||
</div>
|
||
<div class="promo-wms__item">
|
||
<span class="promo-wms__icon">⚙</span>
|
||
<h3>Собственная разработка</h3>
|
||
<p>БИТ.WMS — продукт Первого Бита, гибко адаптируется под ваши процессы</p>
|
||
</div>
|
||
<div class="promo-wms__item">
|
||
<span class="promo-wms__icon">✓</span>
|
||
<h3>Проверено временем</h3>
|
||
<p>200+ проектов внедрения, 15+ лет экспертизы в складской логистике</p>
|
||
</div>
|
||
<div class="promo-wms__item">
|
||
<span class="promo-wms__icon">☆</span>
|
||
<h3>Прозрачные условия</h3>
|
||
<p>Открытая ценовая политика, понятные сроки и этапы</p>
|
||
</div>
|
||
</div>
|
||
<div class="promo-wms__actions">
|
||
<a href="<?php echo esc_url(home_url('/bit-wms/')); ?>" class="btn btn-primary">Подробнее о продукте</a>
|
||
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-outline">Заказать демо</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
```
|
||
|
||
- [ ] **Step 2: Создать блок подписки**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/section-subscribe.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Блок подписки на рассылку
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
?>
|
||
|
||
<section class="subscribe-section">
|
||
<div class="container">
|
||
<h2 class="subscribe-section__title">Получайте экспертные материалы по складской логистике на почту</h2>
|
||
<form class="subscribe-section__form" action="#" method="post">
|
||
<input type="email"
|
||
name="email"
|
||
class="subscribe-section__input"
|
||
placeholder="Ваш email"
|
||
required
|
||
aria-label="Email для подписки" />
|
||
<button type="submit" class="btn btn-primary">Подписаться</button>
|
||
</form>
|
||
<p class="subscribe-section__note">Нажимая кнопку, вы соглашаетесь с <a href="/privacy-policy/">политикой конфиденциальности</a></p>
|
||
</div>
|
||
</section>
|
||
```
|
||
|
||
- [ ] **Step 3: Создать блок клиентов**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/section-clients.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Блок "Наши клиенты"
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
// Логотипы клиентов можно управлять через ACF Options Page или хардкод
|
||
// Для MVP — placeholder-структура
|
||
$clients = [
|
||
['name' => 'Клиент 1', 'logo' => ''],
|
||
['name' => 'Клиент 2', 'logo' => ''],
|
||
['name' => 'Клиент 3', 'logo' => ''],
|
||
['name' => 'Клиент 4', 'logo' => ''],
|
||
['name' => 'Клиент 5', 'logo' => ''],
|
||
['name' => 'Клиент 6', 'logo' => ''],
|
||
];
|
||
?>
|
||
|
||
<section class="clients-section">
|
||
<div class="container">
|
||
<h2 class="clients-section__title">Нам доверяют</h2>
|
||
<div class="clients-section__grid">
|
||
<?php foreach ($clients as $client) : ?>
|
||
<div class="clients-section__item">
|
||
<?php if ($client['logo']) : ?>
|
||
<img src="<?php echo esc_url($client['logo']); ?>"
|
||
alt="<?php echo esc_attr($client['name']); ?>" />
|
||
<?php else : ?>
|
||
<span class="clients-section__placeholder"><?php echo esc_html($client['name']); ?></span>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
```
|
||
|
||
- [ ] **Step 4: Добавить CSS для всех трёх блоков**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Промо-блок БИТ.WMS
|
||
========================================================================== */
|
||
|
||
.promo-wms {
|
||
padding: 80px 0;
|
||
background-color: var(--color-gray-light);
|
||
}
|
||
|
||
.promo-wms__title {
|
||
margin: 0 0 48px;
|
||
}
|
||
|
||
.promo-wms__grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 32px;
|
||
margin-bottom: 48px;
|
||
}
|
||
|
||
.promo-wms__item h3 {
|
||
margin: 0 0 8px;
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.promo-wms__item p {
|
||
margin: 0;
|
||
color: var(--color-gray-text);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.promo-wms__icon {
|
||
font-size: 2rem;
|
||
display: block;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.promo-wms__actions {
|
||
display: flex;
|
||
gap: 16px;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Подписка на рассылку
|
||
========================================================================== */
|
||
|
||
.subscribe-section {
|
||
padding: 80px 0;
|
||
}
|
||
|
||
.subscribe-section__title {
|
||
margin: 0 0 32px;
|
||
max-width: 600px;
|
||
}
|
||
|
||
.subscribe-section__form {
|
||
display: flex;
|
||
gap: 12px;
|
||
max-width: 500px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.subscribe-section__input {
|
||
flex: 1;
|
||
padding: 12px 16px;
|
||
font-size: 1rem;
|
||
font-family: var(--font-body);
|
||
border: 2px solid var(--color-gray-light);
|
||
border-radius: 0;
|
||
background: var(--color-white);
|
||
}
|
||
|
||
.subscribe-section__input:focus {
|
||
outline: none;
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
.subscribe-section__note {
|
||
font-size: 0.75rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Наши клиенты
|
||
========================================================================== */
|
||
|
||
.clients-section {
|
||
padding: 60px 0 80px;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.clients-section__title {
|
||
margin: 0 0 32px;
|
||
}
|
||
|
||
.clients-section__grid {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 32px;
|
||
align-items: center;
|
||
}
|
||
|
||
.clients-section__item img {
|
||
max-height: 40px;
|
||
width: auto;
|
||
filter: grayscale(100%);
|
||
opacity: 0.6;
|
||
transition: filter 0.2s, opacity 0.2s;
|
||
}
|
||
|
||
.clients-section__item img:hover {
|
||
filter: grayscale(0%);
|
||
opacity: 1;
|
||
}
|
||
|
||
.clients-section__placeholder {
|
||
display: inline-block;
|
||
padding: 12px 24px;
|
||
background: var(--color-gray-light);
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.promo-wms__grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.promo-wms__actions {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.subscribe-section__form {
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 5: Проверить все блоки на главной**
|
||
|
||
Открыть `http://bitwms.local`:
|
||
- Промо-блок WMS с 4 преимуществами на сером фоне
|
||
- Блок подписки с полем email
|
||
- Блок клиентов с placeholder-ами
|
||
|
||
- [ ] **Step 6: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add promo WMS, subscribe, and clients sections to front page"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 9: Лента контента с AJAX-фильтрацией на главной
|
||
|
||
**Контекст:** Горизонтальная полоса тегов-фильтров + карточная сетка контента + "Показать ещё". Фильтрация через AJAX без перезагрузки.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/templates/section-filter.php`
|
||
- Создать: `wp-content/themes/bitwms-child/templates/content-card.php`
|
||
- Создать: `wp-content/themes/bitwms-child/inc/ajax-filter.php`
|
||
- Создать: `wp-content/themes/bitwms-child/js/ajax-filter.js`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/inc/enqueue.php`
|
||
|
||
- [ ] **Step 1: Создать шаблон фильтра**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/section-filter.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Блок фильтрации по типам контента
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
$filters = [
|
||
['slug' => 'all', 'label' => 'Все'],
|
||
['slug' => 'post', 'label' => 'Статьи'],
|
||
['slug' => 'case', 'label' => 'Кейсы'],
|
||
['slug' => 'webinar', 'label' => 'Вебинары'],
|
||
['slug' => 'course', 'label' => 'Курсы'],
|
||
['slug' => 'event', 'label' => 'Мероприятия'],
|
||
['slug' => 'material', 'label' => 'Материалы'],
|
||
];
|
||
?>
|
||
|
||
<section class="content-feed">
|
||
<div class="container">
|
||
<div class="filter-bar" role="tablist">
|
||
<?php foreach ($filters as $filter) : ?>
|
||
<button class="filter-bar__btn <?php echo $filter['slug'] === 'all' ? 'filter-bar__btn--active' : ''; ?>"
|
||
data-filter="<?php echo esc_attr($filter['slug']); ?>"
|
||
role="tab"
|
||
aria-selected="<?php echo $filter['slug'] === 'all' ? 'true' : 'false'; ?>">
|
||
<?php echo esc_html($filter['label']); ?>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<div class="content-grid" id="content-grid">
|
||
<?php
|
||
// Начальная загрузка — последние 6 записей из всех CPT
|
||
$initial_query = new WP_Query([
|
||
'post_type' => ['post', 'case', 'webinar', 'course', 'event', 'material'],
|
||
'posts_per_page' => 6,
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
|
||
if ($initial_query->have_posts()) :
|
||
while ($initial_query->have_posts()) :
|
||
$initial_query->the_post();
|
||
get_template_part('templates/content-card');
|
||
endwhile;
|
||
wp_reset_postdata();
|
||
endif;
|
||
?>
|
||
</div>
|
||
|
||
<?php if ($initial_query->found_posts > 6) : ?>
|
||
<div class="content-feed__more">
|
||
<button class="btn btn-outline" id="load-more-btn" data-page="1">Показать ещё</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</section>
|
||
```
|
||
|
||
- [ ] **Step 2: Создать универсальную карточку контента**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/templates/content-card.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Универсальная карточка контента
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
$post_type = get_post_type();
|
||
$type_labels = [
|
||
'post' => 'Статья',
|
||
'case' => 'Кейс',
|
||
'webinar' => 'Вебинар',
|
||
'course' => 'Курс',
|
||
'event' => 'Мероприятие',
|
||
'material' => 'Материал',
|
||
];
|
||
$type_label = $type_labels[$post_type] ?? 'Запись';
|
||
|
||
// Для постов с рубрикой "Новости" — переопределяем метку
|
||
if ($post_type === 'post') {
|
||
$categories = get_the_category();
|
||
foreach ($categories as $cat) {
|
||
if ($cat->slug === 'news') {
|
||
$type_label = 'Новость';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
|
||
<article class="content-card">
|
||
<a href="<?php the_permalink(); ?>" class="content-card__link">
|
||
<?php if (has_post_thumbnail()) : ?>
|
||
<div class="content-card__image">
|
||
<?php the_post_thumbnail('medium_large'); ?>
|
||
</div>
|
||
<?php else : ?>
|
||
<div class="content-card__image content-card__image--placeholder"></div>
|
||
<?php endif; ?>
|
||
|
||
<div class="content-card__body">
|
||
<span class="badge"><?php echo esc_html($type_label); ?></span>
|
||
<h3 class="content-card__title"><?php the_title(); ?></h3>
|
||
<?php if (has_excerpt()) : ?>
|
||
<p class="content-card__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 15)); ?></p>
|
||
<?php endif; ?>
|
||
<div class="content-card__meta">
|
||
<time datetime="<?php echo esc_attr(get_the_date('Y-m-d')); ?>">
|
||
<?php echo esc_html(get_the_date('d.m.Y')); ?>
|
||
</time>
|
||
</div>
|
||
</div>
|
||
</a>
|
||
</article>
|
||
```
|
||
|
||
- [ ] **Step 3: Создать AJAX-обработчик**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/inc/ajax-filter.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* AJAX-фильтрация ленты контента на главной
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
add_action('wp_ajax_bitwms_filter', 'bitwms_ajax_filter');
|
||
add_action('wp_ajax_nopriv_bitwms_filter', 'bitwms_ajax_filter');
|
||
|
||
function bitwms_ajax_filter(): void {
|
||
$post_type = sanitize_text_field($_POST['post_type'] ?? 'all');
|
||
$page = absint($_POST['page'] ?? 1);
|
||
$per_page = 6;
|
||
|
||
$args = [
|
||
'posts_per_page' => $per_page,
|
||
'paged' => $page,
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
];
|
||
|
||
if ($post_type === 'all') {
|
||
$args['post_type'] = ['post', 'case', 'webinar', 'course', 'event', 'material'];
|
||
} else {
|
||
$args['post_type'] = $post_type;
|
||
}
|
||
|
||
$query = new WP_Query($args);
|
||
|
||
ob_start();
|
||
if ($query->have_posts()) {
|
||
while ($query->have_posts()) {
|
||
$query->the_post();
|
||
get_template_part('templates/content-card');
|
||
}
|
||
wp_reset_postdata();
|
||
}
|
||
$html = ob_get_clean();
|
||
|
||
wp_send_json_success([
|
||
'html' => $html,
|
||
'has_more' => $page < $query->max_num_pages,
|
||
]);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Создать JS для AJAX-фильтрации**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/js/ajax-filter.js`:
|
||
|
||
```javascript
|
||
/**
|
||
* AJAX-фильтрация ленты контента + "Показать ещё"
|
||
*/
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const filterBar = document.querySelector('.filter-bar');
|
||
const contentGrid = document.getElementById('content-grid');
|
||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||
|
||
if (!filterBar || !contentGrid) return;
|
||
|
||
let currentFilter = 'all';
|
||
let currentPage = 1;
|
||
|
||
// Фильтрация по типу
|
||
filterBar.addEventListener('click', function (e) {
|
||
const btn = e.target.closest('.filter-bar__btn');
|
||
if (!btn) return;
|
||
|
||
// Обновляем активную кнопку
|
||
filterBar.querySelectorAll('.filter-bar__btn').forEach(function (b) {
|
||
b.classList.remove('filter-bar__btn--active');
|
||
b.setAttribute('aria-selected', 'false');
|
||
});
|
||
btn.classList.add('filter-bar__btn--active');
|
||
btn.setAttribute('aria-selected', 'true');
|
||
|
||
currentFilter = btn.dataset.filter;
|
||
currentPage = 1;
|
||
loadContent(false);
|
||
});
|
||
|
||
// "Показать ещё"
|
||
if (loadMoreBtn) {
|
||
loadMoreBtn.addEventListener('click', function () {
|
||
currentPage++;
|
||
loadContent(true);
|
||
});
|
||
}
|
||
|
||
function loadContent(append) {
|
||
var formData = new FormData();
|
||
formData.append('action', 'bitwms_filter');
|
||
formData.append('post_type', currentFilter);
|
||
formData.append('page', currentPage);
|
||
|
||
fetch(bitwmsAjax.url, {
|
||
method: 'POST',
|
||
body: formData,
|
||
})
|
||
.then(function (response) { return response.json(); })
|
||
.then(function (data) {
|
||
if (data.success) {
|
||
if (append) {
|
||
contentGrid.insertAdjacentHTML('beforeend', data.data.html);
|
||
} else {
|
||
contentGrid.innerHTML = data.data.html;
|
||
}
|
||
|
||
if (loadMoreBtn) {
|
||
loadMoreBtn.style.display = data.data.has_more ? '' : 'none';
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 5: Подключить AJAX-обработчик и скрипт**
|
||
|
||
Добавить `'inc/ajax-filter.php'` в `$bitwms_includes` в `functions.php`:
|
||
|
||
```php
|
||
$bitwms_includes = [
|
||
'inc/enqueue.php',
|
||
'inc/cpt.php',
|
||
'inc/acf-fields.php',
|
||
'inc/ajax-filter.php',
|
||
];
|
||
```
|
||
|
||
Обновить `inc/enqueue.php` — добавить скрипт и локализацию:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Подключение скриптов и стилей
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
add_action('wp_enqueue_scripts', function () {
|
||
$theme_version = wp_get_theme()->get('Version');
|
||
$theme_uri = get_stylesheet_directory_uri();
|
||
|
||
// Боковая навигация
|
||
wp_enqueue_script(
|
||
'bitwms-sidebar-nav',
|
||
$theme_uri . '/js/sidebar-nav.js',
|
||
[],
|
||
$theme_version,
|
||
true
|
||
);
|
||
|
||
// AJAX-фильтрация (только на главной)
|
||
if (is_front_page()) {
|
||
wp_enqueue_script(
|
||
'bitwms-ajax-filter',
|
||
$theme_uri . '/js/ajax-filter.js',
|
||
[],
|
||
$theme_version,
|
||
true
|
||
);
|
||
wp_localize_script('bitwms-ajax-filter', 'bitwmsAjax', [
|
||
'url' => admin_url('admin-ajax.php'),
|
||
]);
|
||
}
|
||
}, 20);
|
||
```
|
||
|
||
- [ ] **Step 6: Добавить CSS для фильтра и сетки карточек**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Фильтр-бар
|
||
========================================================================== */
|
||
|
||
.filter-bar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-bottom: 32px;
|
||
padding-bottom: 24px;
|
||
border-bottom: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.filter-bar__btn {
|
||
padding: 8px 20px;
|
||
font-family: var(--font-body);
|
||
font-size: 0.875rem;
|
||
font-weight: 400;
|
||
background: none;
|
||
border: 1px solid var(--color-gray-light);
|
||
cursor: pointer;
|
||
transition: background-color 0.15s, color 0.15s, border-color 0.15s;
|
||
color: var(--color-black);
|
||
}
|
||
|
||
.filter-bar__btn:hover {
|
||
border-color: var(--color-black);
|
||
}
|
||
|
||
.filter-bar__btn--active {
|
||
background-color: var(--color-black);
|
||
color: var(--color-white);
|
||
border-color: var(--color-black);
|
||
font-weight: 700;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Сетка карточек контента
|
||
========================================================================== */
|
||
|
||
.content-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 24px;
|
||
margin-bottom: 32px;
|
||
}
|
||
|
||
.content-card__link {
|
||
display: block;
|
||
text-decoration: none;
|
||
color: inherit;
|
||
transition: opacity 0.15s;
|
||
}
|
||
|
||
.content-card__link:hover {
|
||
text-decoration: none;
|
||
color: inherit;
|
||
}
|
||
|
||
.content-card__link:hover .content-card__title {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.content-card__image {
|
||
aspect-ratio: 16 / 10;
|
||
overflow: hidden;
|
||
margin-bottom: 16px;
|
||
background-color: var(--color-gray-light);
|
||
}
|
||
|
||
.content-card__image img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.content-card__body .badge {
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.content-card__title {
|
||
font-size: 1.125rem;
|
||
margin: 0 0 8px;
|
||
line-height: 1.3;
|
||
transition: color 0.15s;
|
||
}
|
||
|
||
.content-card__excerpt {
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
margin: 0 0 12px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.content-card__meta {
|
||
font-size: 0.75rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.content-feed__more {
|
||
text-align: center;
|
||
margin-bottom: 60px;
|
||
}
|
||
|
||
@media (max-width: 1024px) {
|
||
.content-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.content-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 7: Проверить фильтрацию**
|
||
|
||
Создать несколько тестовых записей разных типов в админке. Открыть главную:
|
||
- Фильтр-бар с кнопками типов контента
|
||
- Клик по типу фильтрует карточки без перезагрузки
|
||
- "Показать ещё" подгружает следующую порцию
|
||
- Карточки в сетке 3 колонки (2 на планшете, 1 на мобильном)
|
||
|
||
- [ ] **Step 8: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add content feed with AJAX filtering and load more on front page"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 10: Страница продукта БИТ.WMS
|
||
|
||
**Контекст:** Продуктовая страница: герой, функции, "Почему Первый Бит", кейсы, другие решения, форма демо, анкета.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/page-templates/page-bit-wms.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
|
||
- [ ] **Step 1: Создать шаблон страницы БИТ.WMS**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/page-templates/page-bit-wms.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Template Name: БИТ.WMS
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header();
|
||
?>
|
||
|
||
<main class="page-bitwms">
|
||
|
||
<!-- Герой -->
|
||
<section class="bitwms-hero">
|
||
<div class="container">
|
||
<h1>БИТ.WMS</h1>
|
||
<p class="bitwms-hero__subtitle">Комплексное решение для управления складом</p>
|
||
<p class="bitwms-hero__desc">БИТ.WMS — это полнофункциональная система управления складом от компании «Первый Бит». Автоматизирует все складские процессы: от приёмки до отгрузки, с полным контролем на каждом этапе.</p>
|
||
<div class="bitwms-hero__actions">
|
||
<a href="#demo-form" class="btn btn-primary">Заказать демо</a>
|
||
<a href="#" class="btn btn-outline" data-popup="download-presentation">Скачать презентацию</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Функции -->
|
||
<section class="bitwms-features">
|
||
<div class="container">
|
||
<h2>Функции БИТ.WMS</h2>
|
||
<div class="features-grid">
|
||
<?php
|
||
$features = [
|
||
['title' => 'Приёмка', 'desc' => 'Контроль поступающего товара, сверка с заказами, маркировка', 'result' => 'Сокращение времени приёмки на 40%'],
|
||
['title' => 'Размещение', 'desc' => 'Автоматический подбор ячеек хранения по заданным правилам', 'result' => 'Оптимизация использования площади склада'],
|
||
['title' => 'Хранение', 'desc' => 'Адресное хранение, контроль сроков годности, серийных номеров', 'result' => 'Снижение потерь от просрочки'],
|
||
['title' => 'Отбор', 'desc' => 'Волновой и кластерный отбор, оптимизация маршрутов сборки', 'result' => 'Увеличение скорости сборки заказов на 30%'],
|
||
['title' => 'Отгрузка', 'desc' => 'Контроль отгрузки, формирование документов, сверка с заказом', 'result' => 'Снижение ошибок отгрузки до 0,1%'],
|
||
['title' => 'Инвентаризация', 'desc' => 'Плановая и выборочная инвентаризация с ТСД', 'result' => 'Инвентаризация за часы вместо дней'],
|
||
];
|
||
foreach ($features as $f) : ?>
|
||
<div class="feature-card">
|
||
<h3 class="feature-card__title"><?php echo esc_html($f['title']); ?></h3>
|
||
<p class="feature-card__desc"><?php echo esc_html($f['desc']); ?></p>
|
||
<p class="feature-card__result"><strong>Результат:</strong> <?php echo esc_html($f['result']); ?></p>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Почему Первый Бит -->
|
||
<section class="bitwms-why">
|
||
<div class="container">
|
||
<h2>Почему Первый Бит</h2>
|
||
<div class="why-grid">
|
||
<div class="why-item">
|
||
<h3 class="why-item__title">Быстро</h3>
|
||
<p>Мы — профессионалы, знаем бизнес-задачи склада и процессы. Запускаем проекты за недели.</p>
|
||
</div>
|
||
<div class="why-item">
|
||
<h3 class="why-item__title">Просто</h3>
|
||
<p>Знаем все о WMS-решениях и имеем собственный программный продукт БИТ.WMS.</p>
|
||
</div>
|
||
<div class="why-item">
|
||
<h3 class="why-item__title">Качественно</h3>
|
||
<p>Первый Бит — это результат. 200+ успешных проектов, многолетний опыт.</p>
|
||
</div>
|
||
<div class="why-item">
|
||
<h3 class="why-item__title">Открыто</h3>
|
||
<p>Прозрачная ценовая политика. Понятные сроки и этапы внедрения.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Кейсы -->
|
||
<section class="bitwms-cases">
|
||
<div class="container">
|
||
<h2>Кейсы внедрения</h2>
|
||
<div class="content-grid">
|
||
<?php
|
||
$cases_query = new WP_Query([
|
||
'post_type' => 'case',
|
||
'posts_per_page' => 3,
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
if ($cases_query->have_posts()) :
|
||
while ($cases_query->have_posts()) :
|
||
$cases_query->the_post();
|
||
get_template_part('templates/content-card');
|
||
endwhile;
|
||
wp_reset_postdata();
|
||
else : ?>
|
||
<p>Кейсы скоро появятся.</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<p><a href="<?php echo esc_url(home_url('/cases/')); ?>" class="btn btn-outline">Все кейсы</a></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Другие решения -->
|
||
<section class="bitwms-other">
|
||
<div class="container">
|
||
<h2>Возможно, вам будет интересно</h2>
|
||
<div class="other-grid">
|
||
<div class="other-card">
|
||
<h3>1C:WMS Логистика</h3>
|
||
<p>Управление складом на платформе 1С</p>
|
||
</div>
|
||
<div class="other-card">
|
||
<h3>Клеверенс</h3>
|
||
<p>Мобильная автоматизация склада</p>
|
||
</div>
|
||
<div class="other-card">
|
||
<h3>1C:TMS</h3>
|
||
<p>Управление транспортной логистикой</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Форма "Заказать демо" -->
|
||
<section class="bitwms-demo" id="demo-form">
|
||
<div class="container">
|
||
<h2>Заказать демо БИТ.WMS</h2>
|
||
<p>Оставьте заявку, и наш эксперт свяжется с вами для демонстрации системы</p>
|
||
<?php
|
||
// Contact Form 7 shortcode — ID формы подставить после создания
|
||
// echo do_shortcode('[contact-form-7 id="XXX" title="Заказать демо"]');
|
||
?>
|
||
<form class="demo-form" action="#" method="post">
|
||
<div class="demo-form__grid">
|
||
<input type="text" name="name" placeholder="Имя *" required />
|
||
<input type="text" name="company" placeholder="Компания" />
|
||
<input type="tel" name="phone" placeholder="Телефон *" required />
|
||
<input type="email" name="email" placeholder="Email *" required />
|
||
</div>
|
||
<textarea name="comment" placeholder="Комментарий" rows="3"></textarea>
|
||
<label class="demo-form__consent">
|
||
<input type="checkbox" required />
|
||
Согласен на <a href="/privacy-policy/" target="_blank">обработку персональных данных</a>
|
||
</label>
|
||
<button type="submit" class="btn btn-primary">Отправить заявку</button>
|
||
</form>
|
||
<p class="demo-form__anketa">
|
||
Нужен детальный расчёт? <a href="<?php echo esc_url(home_url('/bit-wms/anketa/')); ?>">Заполните анкету</a>
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<?php
|
||
get_footer();
|
||
```
|
||
|
||
- [ ] **Step 2: Добавить CSS для страницы БИТ.WMS**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Страница БИТ.WMS
|
||
========================================================================== */
|
||
|
||
.bitwms-hero {
|
||
padding: 80px 0 60px;
|
||
}
|
||
|
||
.bitwms-hero h1 {
|
||
font-size: 4rem;
|
||
margin: 0 0 16px;
|
||
}
|
||
|
||
.bitwms-hero__subtitle {
|
||
font-size: 1.5rem;
|
||
color: var(--color-gray-text);
|
||
margin: 0 0 24px;
|
||
}
|
||
|
||
.bitwms-hero__desc {
|
||
font-size: 1.125rem;
|
||
line-height: 1.6;
|
||
max-width: 700px;
|
||
margin: 0 0 32px;
|
||
}
|
||
|
||
.bitwms-hero__actions {
|
||
display: flex;
|
||
gap: 16px;
|
||
}
|
||
|
||
/* Функции */
|
||
.bitwms-features {
|
||
padding: 80px 0;
|
||
background-color: var(--color-gray-light);
|
||
}
|
||
|
||
.features-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 24px;
|
||
margin-top: 32px;
|
||
}
|
||
|
||
.feature-card {
|
||
background: var(--color-white);
|
||
padding: 32px;
|
||
}
|
||
|
||
.feature-card__title {
|
||
margin: 0 0 12px;
|
||
}
|
||
|
||
.feature-card__desc {
|
||
color: var(--color-gray-text);
|
||
line-height: 1.6;
|
||
margin: 0 0 16px;
|
||
}
|
||
|
||
.feature-card__result {
|
||
font-size: 0.875rem;
|
||
color: var(--color-primary);
|
||
margin: 0;
|
||
}
|
||
|
||
/* Почему Первый Бит */
|
||
.bitwms-why {
|
||
padding: 80px 0;
|
||
}
|
||
|
||
.why-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 32px;
|
||
margin-top: 32px;
|
||
}
|
||
|
||
.why-item__title {
|
||
font-size: 1.5rem;
|
||
margin: 0 0 12px;
|
||
}
|
||
|
||
.why-item p {
|
||
color: var(--color-gray-text);
|
||
line-height: 1.6;
|
||
margin: 0;
|
||
}
|
||
|
||
/* Кейсы */
|
||
.bitwms-cases {
|
||
padding: 60px 0;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
/* Другие решения */
|
||
.bitwms-other {
|
||
padding: 60px 0;
|
||
background-color: var(--color-gray-light);
|
||
}
|
||
|
||
.other-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 24px;
|
||
margin-top: 32px;
|
||
}
|
||
|
||
.other-card {
|
||
background: var(--color-white);
|
||
padding: 32px;
|
||
}
|
||
|
||
.other-card h3 {
|
||
margin: 0 0 8px;
|
||
}
|
||
|
||
.other-card p {
|
||
color: var(--color-gray-text);
|
||
margin: 0;
|
||
}
|
||
|
||
/* Форма демо */
|
||
.bitwms-demo {
|
||
padding: 80px 0;
|
||
}
|
||
|
||
.demo-form {
|
||
max-width: 600px;
|
||
margin-top: 24px;
|
||
}
|
||
|
||
.demo-form__grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 12px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.demo-form input[type="text"],
|
||
.demo-form input[type="tel"],
|
||
.demo-form input[type="email"],
|
||
.demo-form textarea {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
font-family: var(--font-body);
|
||
font-size: 1rem;
|
||
border: 2px solid var(--color-gray-light);
|
||
border-radius: 0;
|
||
background: var(--color-white);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.demo-form input:focus,
|
||
.demo-form textarea:focus {
|
||
outline: none;
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
.demo-form textarea {
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.demo-form__consent {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 8px;
|
||
font-size: 0.875rem;
|
||
margin-bottom: 24px;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.demo-form__anketa {
|
||
margin-top: 24px;
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.bitwms-hero h1 {
|
||
font-size: 2.5rem;
|
||
}
|
||
|
||
.bitwms-hero__actions {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.features-grid,
|
||
.other-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.why-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.demo-form__grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Создать страницу в WP и назначить шаблон**
|
||
|
||
В админке WP: создать страницу "БИТ.WMS" со slug `bit-wms`, назначить шаблон "БИТ.WMS".
|
||
|
||
- [ ] **Step 4: Проверить страницу**
|
||
|
||
Открыть `http://bitwms.local/bit-wms/`:
|
||
- Все секции отображаются
|
||
- Форма демо работает визуально
|
||
- Адаптивность на мобильном
|
||
|
||
- [ ] **Step 5: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add BIT.WMS product page template with features, benefits, and demo form"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 11: Архивные шаблоны и детальные страницы CPT
|
||
|
||
**Контекст:** Единый шаблон архива для всех CPT + детальные шаблоны для кейсов, вебинаров, курсов, мероприятий.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/archive/archive-cpt.php`
|
||
- Создать: `wp-content/themes/bitwms-child/template-parts/single-case.php`
|
||
- Создать: `wp-content/themes/bitwms-child/template-parts/single-webinar.php`
|
||
- Создать: `wp-content/themes/bitwms-child/template-parts/single-course.php`
|
||
- Создать: `wp-content/themes/bitwms-child/template-parts/single-event.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
|
||
- [ ] **Step 1: Создать архивные шаблоны**
|
||
|
||
WordPress ищет шаблоны по иерархии: `archive-{post_type}.php`. Создаём по одному для каждого CPT (все используют единый layout).
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/archive-case.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Архив Кейсов
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header();
|
||
?>
|
||
|
||
<main class="archive-page">
|
||
<div class="container">
|
||
<h1 class="archive-page__title">Кейсы</h1>
|
||
|
||
<div class="content-grid">
|
||
<?php
|
||
if (have_posts()) :
|
||
while (have_posts()) :
|
||
the_post();
|
||
get_template_part('templates/content-card');
|
||
endwhile;
|
||
else : ?>
|
||
<p>Кейсы скоро появятся.</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php the_posts_pagination([
|
||
'prev_text' => '←',
|
||
'next_text' => '→',
|
||
]); ?>
|
||
</div>
|
||
</main>
|
||
|
||
<?php
|
||
get_footer();
|
||
```
|
||
|
||
Создать аналогичные файлы для остальных CPT — `archive-webinar.php`, `archive-course.php`, `archive-event.php`, `archive-material.php` — меняя только заголовок H1 ("Вебинары", "Курсы", "Мероприятия", "Материалы") и текст "не найдено".
|
||
|
||
- [ ] **Step 2: Создать детальный шаблон кейса**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/single-case.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Детальная страница кейса
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header();
|
||
the_post();
|
||
|
||
$client = get_field('case_client');
|
||
$industry = get_field('case_industry');
|
||
$task = get_field('case_task');
|
||
$solution = get_field('case_solution');
|
||
$result = get_field('case_result');
|
||
$quote = get_field('case_quote');
|
||
$gallery = get_field('case_gallery');
|
||
?>
|
||
|
||
<main class="single-case">
|
||
<div class="container">
|
||
<article>
|
||
<h1><?php the_title(); ?></h1>
|
||
|
||
<div class="single-case__meta">
|
||
<?php if ($client) : ?>
|
||
<div class="single-case__meta-item">
|
||
<strong>Клиент:</strong> <?php echo esc_html($client); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if ($industry) : ?>
|
||
<div class="single-case__meta-item">
|
||
<strong>Отрасль:</strong> <?php echo esc_html($industry); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if ($task) : ?>
|
||
<section class="single-case__section">
|
||
<h2>Задача</h2>
|
||
<?php echo wp_kses_post($task); ?>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($solution) : ?>
|
||
<section class="single-case__section">
|
||
<h2>Решение</h2>
|
||
<?php echo wp_kses_post($solution); ?>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($result) : ?>
|
||
<section class="single-case__section">
|
||
<h2>Результат</h2>
|
||
<?php echo wp_kses_post($result); ?>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($gallery) : ?>
|
||
<section class="single-case__gallery">
|
||
<h2>Галерея</h2>
|
||
<div class="gallery-grid">
|
||
<?php foreach ($gallery as $img) : ?>
|
||
<a href="<?php echo esc_url($img['url']); ?>" target="_blank">
|
||
<img src="<?php echo esc_url($img['sizes']['medium_large']); ?>"
|
||
alt="<?php echo esc_attr($img['alt']); ?>" />
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($quote) : ?>
|
||
<blockquote class="single-case__quote">
|
||
<p><?php echo esc_html($quote); ?></p>
|
||
</blockquote>
|
||
<?php endif; ?>
|
||
|
||
<div class="single-case__cta">
|
||
<p>Хотите такой же результат?</p>
|
||
<a href="<?php echo esc_url(home_url('/bit-wms/#demo-form')); ?>" class="btn btn-primary">Закажите консультацию</a>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Похожие кейсы -->
|
||
<section class="related-posts">
|
||
<h2>Другие кейсы</h2>
|
||
<div class="content-grid">
|
||
<?php
|
||
$related = new WP_Query([
|
||
'post_type' => 'case',
|
||
'posts_per_page' => 3,
|
||
'post__not_in' => [get_the_ID()],
|
||
'orderby' => 'rand',
|
||
]);
|
||
if ($related->have_posts()) :
|
||
while ($related->have_posts()) :
|
||
$related->the_post();
|
||
get_template_part('templates/content-card');
|
||
endwhile;
|
||
wp_reset_postdata();
|
||
endif;
|
||
?>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
|
||
<?php
|
||
get_footer();
|
||
```
|
||
|
||
- [ ] **Step 3: Создать детальные шаблоны вебинара, курса, мероприятия**
|
||
|
||
Создать `single-webinar.php`, `single-course.php`, `single-event.php` по аналогичной структуре, используя соответствующие ACF-поля из Task 6. Каждый шаблон содержит:
|
||
- Заголовок H1
|
||
- ACF-поля в нужном порядке
|
||
- CTA-блок внизу (регистрация / запись)
|
||
- Блок "Похожие" (3 карточки того же типа)
|
||
|
||
- [ ] **Step 4: Добавить CSS для детальных страниц**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Архивные страницы
|
||
========================================================================== */
|
||
|
||
.archive-page {
|
||
padding: 60px 0;
|
||
}
|
||
|
||
.archive-page__title {
|
||
margin: 0 0 32px;
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Детальные страницы
|
||
========================================================================== */
|
||
|
||
.single-case,
|
||
.single-webinar,
|
||
.single-course,
|
||
.single-event {
|
||
padding: 60px 0;
|
||
}
|
||
|
||
.single-case__meta {
|
||
display: flex;
|
||
gap: 24px;
|
||
margin-bottom: 40px;
|
||
padding-bottom: 24px;
|
||
border-bottom: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.single-case__meta-item {
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.single-case__section {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.single-case__section h2 {
|
||
font-size: 1.5rem;
|
||
margin: 0 0 16px;
|
||
}
|
||
|
||
.gallery-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 16px;
|
||
margin-top: 16px;
|
||
}
|
||
|
||
.gallery-grid img {
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
|
||
.single-case__quote {
|
||
border-left: 4px solid var(--color-primary);
|
||
padding: 24px 32px;
|
||
margin: 40px 0;
|
||
background-color: var(--color-gray-light);
|
||
font-style: italic;
|
||
font-size: 1.125rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.single-case__cta {
|
||
padding: 40px 0;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.single-case__cta p {
|
||
font-size: 1.25rem;
|
||
font-weight: 700;
|
||
margin: 0 0 16px;
|
||
}
|
||
|
||
.related-posts {
|
||
padding: 60px 0 0;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
}
|
||
|
||
.related-posts h2 {
|
||
margin: 0 0 24px;
|
||
}
|
||
|
||
/* Пагинация */
|
||
.nav-links {
|
||
display: flex;
|
||
gap: 8px;
|
||
justify-content: center;
|
||
margin-top: 32px;
|
||
}
|
||
|
||
.nav-links .page-numbers {
|
||
padding: 8px 16px;
|
||
border: 1px solid var(--color-gray-light);
|
||
color: var(--color-black);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.nav-links .page-numbers.current {
|
||
background: var(--color-black);
|
||
color: var(--color-white);
|
||
border-color: var(--color-black);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.single-case__meta {
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.gallery-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 5: Проверить архивы и детальные страницы**
|
||
|
||
Создать тестовые записи каждого типа. Проверить:
|
||
- `/cases/` — архив кейсов с карточками
|
||
- `/cases/test-case/` — детальная страница с ACF-полями
|
||
- Аналогично для вебинаров, курсов, мероприятий, материалов
|
||
|
||
- [ ] **Step 6: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add archive and single templates for all custom post types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 12: Страница контактов и футер
|
||
|
||
**Контекст:** Страница контактов с формой обратной связи. Кастомный футер с колонками.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/page-templates/page-contacts.php`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php` (футер)
|
||
- Модифицировать: `wp-content/themes/bitwms-child/style.css`
|
||
|
||
- [ ] **Step 1: Создать шаблон страницы контактов**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/page-templates/page-contacts.php`:
|
||
|
||
```php
|
||
<?php
|
||
/**
|
||
* Template Name: Контакты
|
||
*
|
||
* @package bitwms
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
get_header();
|
||
?>
|
||
|
||
<main class="page-contacts">
|
||
<div class="container">
|
||
<h1>Контакты</h1>
|
||
|
||
<div class="contacts-grid">
|
||
<div class="contacts-info">
|
||
<h2>Екатеринбург Проектный центр</h2>
|
||
<p><strong>Телефон:</strong> <a href="tel:+73432000000">+7 (343) 200-00-00</a></p>
|
||
<p><strong>Email:</strong> <a href="mailto:wms@1bit.ru">wms@1bit.ru</a></p>
|
||
<p><strong>Адрес:</strong> г. Екатеринбург</p>
|
||
</div>
|
||
|
||
<div class="contacts-form">
|
||
<h2>Напишите нам</h2>
|
||
<?php // echo do_shortcode('[contact-form-7 id="XXX" title="Обратная связь"]'); ?>
|
||
<form action="#" method="post">
|
||
<input type="text" name="name" placeholder="Имя *" required />
|
||
<input type="email" name="email" placeholder="Email *" required />
|
||
<textarea name="message" placeholder="Сообщение" rows="5"></textarea>
|
||
<label class="demo-form__consent">
|
||
<input type="checkbox" required />
|
||
Согласен на <a href="/privacy-policy/" target="_blank">обработку персональных данных</a>
|
||
</label>
|
||
<button type="submit" class="btn btn-primary">Отправить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<?php
|
||
get_footer();
|
||
```
|
||
|
||
- [ ] **Step 2: Настроить кастомный футер**
|
||
|
||
Добавить в `functions.php`:
|
||
|
||
```php
|
||
// Кастомный футер
|
||
add_action('generate_before_footer_content', function () {
|
||
?>
|
||
<div class="custom-footer">
|
||
<div class="container">
|
||
<div class="custom-footer__grid">
|
||
<div class="custom-footer__col">
|
||
<img src="<?php echo esc_url(get_stylesheet_directory_uri() . '/img/logo.svg'); ?>"
|
||
alt="первыйБит" height="24" />
|
||
<p>Екатеринбург Проектный центр</p>
|
||
<p><a href="tel:+73432000000">+7 (343) 200-00-00</a></p>
|
||
<p><a href="mailto:wms@1bit.ru">wms@1bit.ru</a></p>
|
||
</div>
|
||
<div class="custom-footer__col">
|
||
<h4>Разделы</h4>
|
||
<ul>
|
||
<li><a href="/cases/">Кейсы</a></li>
|
||
<li><a href="/articles/">Статьи</a></li>
|
||
<li><a href="/webinars/">Вебинары</a></li>
|
||
<li><a href="/courses/">Курсы</a></li>
|
||
<li><a href="/events/">Мероприятия</a></li>
|
||
<li><a href="/materials/">Материалы</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="custom-footer__col">
|
||
<h4>Продукты</h4>
|
||
<ul>
|
||
<li><a href="/bit-wms/">БИТ.WMS</a></li>
|
||
<li>1C:WMS</li>
|
||
<li>Клеверенс</li>
|
||
<li>1C:TMS</li>
|
||
</ul>
|
||
</div>
|
||
<div class="custom-footer__col">
|
||
<h4>Подписка</h4>
|
||
<form class="footer-subscribe" action="#" method="post">
|
||
<input type="email" placeholder="Ваш email" required />
|
||
<button type="submit" class="btn btn-primary btn-sm">OK</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<div class="custom-footer__bottom">
|
||
<p>© <?php echo date('Y'); ?> Первый Бит. Все права защищены.</p>
|
||
<div class="custom-footer__legal">
|
||
<a href="/privacy-policy/">Политика конфиденциальности</a>
|
||
<a href="/consent/">Согласие на обработку данных</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}, 5);
|
||
```
|
||
|
||
- [ ] **Step 3: Добавить CSS футера и контактов**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Страница контактов
|
||
========================================================================== */
|
||
|
||
.page-contacts {
|
||
padding: 60px 0;
|
||
}
|
||
|
||
.contacts-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 48px;
|
||
margin-top: 32px;
|
||
}
|
||
|
||
.contacts-info p {
|
||
line-height: 1.8;
|
||
}
|
||
|
||
.contacts-form input,
|
||
.contacts-form textarea {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
font-family: var(--font-body);
|
||
font-size: 1rem;
|
||
border: 2px solid var(--color-gray-light);
|
||
border-radius: 0;
|
||
margin-bottom: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.contacts-form input:focus,
|
||
.contacts-form textarea:focus {
|
||
outline: none;
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Футер
|
||
========================================================================== */
|
||
|
||
.custom-footer {
|
||
border-top: 1px solid var(--color-gray-light);
|
||
padding: 48px 0 24px;
|
||
}
|
||
|
||
.custom-footer__grid {
|
||
display: grid;
|
||
grid-template-columns: 2fr 1fr 1fr 1.5fr;
|
||
gap: 32px;
|
||
margin-bottom: 32px;
|
||
}
|
||
|
||
.custom-footer__col h4 {
|
||
font-size: 0.875rem;
|
||
margin: 0 0 16px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
.custom-footer__col ul {
|
||
list-style: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.custom-footer__col li {
|
||
margin-bottom: 8px;
|
||
font-size: 0.875rem;
|
||
}
|
||
|
||
.custom-footer__col a {
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.custom-footer__col a:hover {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.custom-footer__col p {
|
||
font-size: 0.875rem;
|
||
color: var(--color-gray-text);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.footer-subscribe {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
|
||
.footer-subscribe input {
|
||
flex: 1;
|
||
padding: 8px 12px;
|
||
font-size: 0.875rem;
|
||
border: 2px solid var(--color-gray-light);
|
||
border-radius: 0;
|
||
}
|
||
|
||
.custom-footer__bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding-top: 24px;
|
||
border-top: 1px solid var(--color-gray-light);
|
||
font-size: 0.75rem;
|
||
color: var(--color-gray-text);
|
||
}
|
||
|
||
.custom-footer__legal {
|
||
display: flex;
|
||
gap: 24px;
|
||
}
|
||
|
||
.custom-footer__legal a {
|
||
color: var(--color-gray-text);
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.contacts-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.custom-footer__grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.custom-footer__bottom {
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
text-align: center;
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Создать страницу "Контакты" в WP, назначить шаблон**
|
||
|
||
- [ ] **Step 5: Проверить контакты и футер**
|
||
|
||
- [ ] **Step 6: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add contacts page template and custom footer"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 13: Формы Contact Form 7 и gated-контент
|
||
|
||
**Контекст:** Настраиваем реальные формы CF7 для всех точек лидогенерации. Gated-контент для материалов.
|
||
|
||
**Файлы:**
|
||
- Создать: `wp-content/themes/bitwms-child/js/gated-content.js`
|
||
- Модифицировать: `wp-content/themes/bitwms-child/inc/enqueue.php`
|
||
|
||
- [ ] **Step 1: Создать формы Contact Form 7 в админке**
|
||
|
||
В админке WP > Contact > Add New. Создать 5 форм:
|
||
|
||
**Форма "Заказать демо":**
|
||
```
|
||
[text* your-name placeholder "Имя"]
|
||
[text your-company placeholder "Компания"]
|
||
[tel* your-phone placeholder "Телефон"]
|
||
[email* your-email placeholder "Email"]
|
||
[textarea your-comment placeholder "Комментарий"]
|
||
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
|
||
[submit "Отправить заявку"]
|
||
```
|
||
|
||
**Форма "Получить консультацию":**
|
||
```
|
||
[text* your-name placeholder "Имя"]
|
||
[tel* your-phone placeholder "Телефон"]
|
||
[email* your-email placeholder "Email"]
|
||
[textarea your-question placeholder "Ваш вопрос"]
|
||
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
|
||
[submit "Отправить"]
|
||
```
|
||
|
||
**Форма "Зарегистрироваться":**
|
||
```
|
||
[text* your-name placeholder "Имя"]
|
||
[email* your-email placeholder "Email"]
|
||
[tel your-phone placeholder "Телефон"]
|
||
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
|
||
[submit "Зарегистрироваться"]
|
||
```
|
||
|
||
**Форма "Скачать материал" (gated):**
|
||
```
|
||
[text* your-name placeholder "Имя"]
|
||
[email* your-email placeholder "Email"]
|
||
[hidden material-id]
|
||
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
|
||
[submit "Скачать"]
|
||
```
|
||
|
||
**Форма "Обратная связь":**
|
||
```
|
||
[text* your-name placeholder "Имя"]
|
||
[email* your-email placeholder "Email"]
|
||
[textarea* your-message placeholder "Сообщение"]
|
||
[acceptance consent] Согласен на [обработку персональных данных](/privacy-policy/) [/acceptance]
|
||
[submit "Отправить"]
|
||
```
|
||
|
||
Для каждой формы настроить email-уведомление на адрес wms@1bit.ru.
|
||
|
||
- [ ] **Step 2: Заменить placeholder-формы на шорткоды CF7**
|
||
|
||
Обновить шаблоны `page-bit-wms.php`, `page-contacts.php` — заменить HTML-формы на `echo do_shortcode('[contact-form-7 id="ID" title="Название"]');` с реальными ID форм.
|
||
|
||
- [ ] **Step 3: Создать JS для gated-контента**
|
||
|
||
Создать файл `wp-content/themes/bitwms-child/js/gated-content.js`:
|
||
|
||
```javascript
|
||
/**
|
||
* Gated-контент — модальное окно для скачивания материалов за email
|
||
*/
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
var modal = document.getElementById('gated-modal');
|
||
if (!modal) return;
|
||
|
||
var overlay = modal.querySelector('.gated-modal__overlay');
|
||
var closeBtn = modal.querySelector('.gated-modal__close');
|
||
|
||
// Открытие модального окна по data-gated
|
||
document.addEventListener('click', function (e) {
|
||
var trigger = e.target.closest('[data-gated]');
|
||
if (!trigger) return;
|
||
|
||
e.preventDefault();
|
||
var materialId = trigger.dataset.gated;
|
||
var downloadUrl = trigger.dataset.downloadUrl;
|
||
|
||
// Установить hidden-поле с ID материала
|
||
var hiddenField = modal.querySelector('input[name="material-id"]');
|
||
if (hiddenField) {
|
||
hiddenField.value = materialId;
|
||
}
|
||
|
||
// Сохранить URL для скачивания
|
||
modal.dataset.downloadUrl = downloadUrl || '';
|
||
|
||
modal.classList.add('gated-modal--open');
|
||
document.body.style.overflow = 'hidden';
|
||
});
|
||
|
||
// Закрытие
|
||
function closeModal() {
|
||
modal.classList.remove('gated-modal--open');
|
||
document.body.style.overflow = '';
|
||
}
|
||
|
||
if (closeBtn) closeBtn.addEventListener('click', closeModal);
|
||
if (overlay) overlay.addEventListener('click', closeModal);
|
||
|
||
// После успешной отправки CF7 — скачать файл
|
||
document.addEventListener('wpcf7mailsent', function (e) {
|
||
if (modal.classList.contains('gated-modal--open') && modal.dataset.downloadUrl) {
|
||
window.open(modal.dataset.downloadUrl, '_blank');
|
||
closeModal();
|
||
}
|
||
});
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 4: Добавить HTML модального окна в footer**
|
||
|
||
Добавить в `functions.php`:
|
||
|
||
```php
|
||
// Модальное окно gated-контента
|
||
add_action('wp_footer', function () {
|
||
?>
|
||
<div id="gated-modal" class="gated-modal">
|
||
<div class="gated-modal__overlay"></div>
|
||
<div class="gated-modal__content">
|
||
<button class="gated-modal__close" aria-label="Закрыть">×</button>
|
||
<h3>Скачать материал</h3>
|
||
<p>Укажите ваши данные для получения доступа к материалу</p>
|
||
<?php // echo do_shortcode('[contact-form-7 id="ID" title="Скачать материал"]'); ?>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 5: Добавить CSS модального окна**
|
||
|
||
Добавить в `style.css`:
|
||
|
||
```css
|
||
/* ==========================================================================
|
||
Модальное окно (gated-контент)
|
||
========================================================================== */
|
||
|
||
.gated-modal {
|
||
display: none;
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 2000;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.gated-modal--open {
|
||
display: flex;
|
||
}
|
||
|
||
.gated-modal__overlay {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.gated-modal__content {
|
||
position: relative;
|
||
background: var(--color-white);
|
||
padding: 48px;
|
||
max-width: 480px;
|
||
width: 90%;
|
||
z-index: 1;
|
||
}
|
||
|
||
.gated-modal__close {
|
||
position: absolute;
|
||
top: 16px;
|
||
right: 16px;
|
||
background: none;
|
||
border: none;
|
||
font-size: 1.5rem;
|
||
cursor: pointer;
|
||
color: var(--color-gray-text);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 6: Подключить скрипт в enqueue.php**
|
||
|
||
Добавить в `inc/enqueue.php`:
|
||
|
||
```php
|
||
// Gated-контент
|
||
wp_enqueue_script(
|
||
'bitwms-gated-content',
|
||
$theme_uri . '/js/gated-content.js',
|
||
[],
|
||
$theme_version,
|
||
true
|
||
);
|
||
```
|
||
|
||
- [ ] **Step 7: Проверить формы и gated-контент**
|
||
|
||
- [ ] **Step 8: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add Contact Form 7 forms and gated content modal"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 14: Попапы, JivoSite, callback, аналитика
|
||
|
||
**Контекст:** Финальный слой лидогенерации: попапы (exit-intent, таймер), виджеты JivoSite и callback, аналитика.
|
||
|
||
**Файлы:**
|
||
- Модифицировать: `wp-content/themes/bitwms-child/functions.php`
|
||
|
||
- [ ] **Step 1: Настроить Popup Maker**
|
||
|
||
В админке WP > Popup Maker > Add New:
|
||
|
||
**Попап "Exit-intent — Подписка":**
|
||
- Содержимое: "Не уходите! Подпишитесь на экспертные материалы по складской логистике" + форма email
|
||
- Триггер: Exit Intent
|
||
- Условия: все страницы
|
||
- Настройки: показывать 1 раз за сессию
|
||
|
||
**Попап "Таймер — Демо":**
|
||
- Содержимое: "Хотите увидеть БИТ.WMS в действии?" + CTA "Заказать демо"
|
||
- Триггер: Time Delay — 60 секунд
|
||
- Условия: только страница БИТ.WMS
|
||
- Настройки: показывать 1 раз за сессию
|
||
|
||
- [ ] **Step 2: Подключить JivoSite**
|
||
|
||
Добавить в `functions.php`:
|
||
|
||
```php
|
||
// JivoSite — виджет онлайн-консультанта
|
||
add_action('wp_footer', function () {
|
||
// Подставить реальный widget_id из кабинета JivoSite
|
||
?>
|
||
<!-- JivoSite -->
|
||
<script src="//code.jivo.ru/widget/XXXXXXXX" async></script>
|
||
<?php
|
||
}, 99);
|
||
```
|
||
|
||
Настройка автоприглашения через 30 сек — в панели управления JivoSite (Настройки > Проактивные приглашения), указать страницы: главная, /bit-wms/, /cases/.
|
||
|
||
- [ ] **Step 3: Подключить callback-виджет**
|
||
|
||
Добавить в `functions.php`:
|
||
|
||
```php
|
||
// Callback-виджет
|
||
add_action('wp_footer', function () {
|
||
// Подставить реальный код виджета из кабинета callback-hunter или аналога
|
||
?>
|
||
<!-- Callback Widget -->
|
||
<!-- <script src="https://cdn.callbackhunter.com/XXXXX.js" async></script> -->
|
||
<?php
|
||
}, 99);
|
||
```
|
||
|
||
- [ ] **Step 4: Подключить Яндекс.Метрику и GA4**
|
||
|
||
Добавить в `functions.php`:
|
||
|
||
```php
|
||
// Аналитика — Яндекс.Метрика + GA4
|
||
add_action('wp_head', function () {
|
||
?>
|
||
<!-- Yandex.Metrika counter -->
|
||
<!-- Подставить реальный ID счётчика -->
|
||
<!--
|
||
<script type="text/javascript">
|
||
(function(m,e,t,r,i,k,a){...})(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||
ym(XXXXXXXX, "init", {
|
||
clickmap:true,
|
||
trackLinks:true,
|
||
accurateTrackBounce:true,
|
||
webvisor:true
|
||
});
|
||
</script>
|
||
-->
|
||
|
||
<!-- Google Analytics 4 -->
|
||
<!-- Подставить реальный ID GA4 -->
|
||
<!--
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag(){dataLayer.push(arguments);}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-XXXXXXXXXX');
|
||
</script>
|
||
-->
|
||
<?php
|
||
}, 1);
|
||
```
|
||
|
||
Цели в Яндекс.Метрике настраиваются через интерфейс метрики после получения ID счётчика.
|
||
|
||
- [ ] **Step 5: Настроить Yoast SEO**
|
||
|
||
В админке WP > SEO > General:
|
||
- Указать название организации: "Первый Бит"
|
||
- Schema.org: тип организации — Company
|
||
- Social: указать ссылки на VK, Telegram
|
||
|
||
Для каждой страницы/записи: заполнить SEO-заголовок и мета-описание.
|
||
|
||
- [ ] **Step 6: Проверить все виджеты**
|
||
|
||
- JivoSite виджет отображается в правом нижнем углу
|
||
- Попап exit-intent срабатывает при уходе с сайта
|
||
- Попап таймера появляется через 60 сек на странице БИТ.WMS
|
||
|
||
- [ ] **Step 7: Коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "feat: add popups, JivoSite, callback widget, and analytics tracking"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 15: Финальная проверка и полировка
|
||
|
||
**Контекст:** Проверяем весь сайт целиком: все страницы, формы, адаптивность, производительность.
|
||
|
||
- [ ] **Step 1: Проверить все страницы**
|
||
|
||
Пройти по каждой странице и убедиться:
|
||
- Главная: герой, фильтр, лента, промо WMS, подписка, клиенты
|
||
- БИТ.WMS: герой, функции, "почему", кейсы, другие решения, демо-форма
|
||
- Архивы: кейсы, статьи, вебинары, курсы, мероприятия, материалы
|
||
- Детальные: каждый тип записи с ACF-полями
|
||
- Контакты: информация + форма
|
||
- Футер: на всех страницах
|
||
|
||
- [ ] **Step 2: Проверить адаптивность**
|
||
|
||
Протестировать все страницы на разрешениях:
|
||
- Desktop: 1920px, 1440px, 1280px
|
||
- Tablet: 1024px, 768px
|
||
- Mobile: 375px, 320px
|
||
|
||
Убедиться:
|
||
- Боковая панель скрывается < 768px, гамбургер работает
|
||
- Сетки переходят в 1 колонку
|
||
- Формы занимают полную ширину
|
||
- Текст читабелен
|
||
|
||
- [ ] **Step 3: Проверить формы**
|
||
|
||
Отправить тестовые данные через каждую форму:
|
||
- Заказать демо
|
||
- Получить консультацию
|
||
- Зарегистрироваться на вебинар
|
||
- Скачать материал (gated)
|
||
- Обратная связь
|
||
|
||
Убедиться что email-уведомления приходят.
|
||
|
||
- [ ] **Step 4: Проверить производительность**
|
||
|
||
```bash
|
||
# Установить плагин кеширования (опционально)
|
||
wp plugin install wp-super-cache --activate
|
||
```
|
||
|
||
Проверить в Google PageSpeed Insights или Lighthouse:
|
||
- Целевые показатели: LCP < 2.5s, CLS < 0.1
|
||
- Шрифты загружаются с `font-display: swap`
|
||
- Изображения оптимизированы
|
||
|
||
- [ ] **Step 5: Создать страницы юридических документов**
|
||
|
||
```bash
|
||
wp post create --post_type=page --post_title='Политика конфиденциальности' --post_name='privacy-policy' --post_status=publish
|
||
wp post create --post_type=page --post_title='Согласие на обработку персональных данных' --post_name='consent' --post_status=publish
|
||
```
|
||
|
||
Заполнить юридический текст (предоставляется заказчиком).
|
||
|
||
- [ ] **Step 6: Финальный коммит**
|
||
|
||
```bash
|
||
git add themes/bitwms-child/
|
||
git commit -m "chore: final polish - responsive fixes, performance, legal pages"
|
||
```
|