feat: улучшения формы и отображение case_taxonomy
- Добавлено отображение case_taxonomy вместо 'Разобрались' на странице кейса - Улучшена интеграция iframe формы с обработкой событий - Добавлен лог диалога по интеграции React формы
This commit is contained in:
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# WordPress
|
||||||
|
wp-config.php
|
||||||
|
wp-content/uploads/
|
||||||
|
wp-content/cache/
|
||||||
|
wp-content/backup-db/
|
||||||
|
wp-content/advanced-cache.php
|
||||||
|
wp-content/wp-cache-config.php
|
||||||
|
|
||||||
|
# Node
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
148
DIALOG_LOG_2025-01-16.md
Normal file
148
DIALOG_LOG_2025-01-16.md
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# Лог диалога: Интеграция React формы в WordPress
|
||||||
|
|
||||||
|
**Дата:** 16 января 2025
|
||||||
|
**Тема:** Обсуждение интеграции сложной React формы из Docker в WordPress
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
|
||||||
|
У пользователя есть сложная форма обращений на React, которая:
|
||||||
|
- Развёрнута в Docker контейнере (`ticket_form_frontend_prod`)
|
||||||
|
- Находится по адресу: `https://aiform.clientright.ru/`
|
||||||
|
- Использует Vite, React, TypeScript, Ant Design
|
||||||
|
- Имеет множество шагов, запросов и ответов
|
||||||
|
- Текущая интеграция в WordPress через iframe в `page-form.php`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Обсуждённые темы
|
||||||
|
|
||||||
|
### 1. Использование taxonomy для кейсов
|
||||||
|
|
||||||
|
- Поле `case_taxonomy` используется для фильтрации кейсов в архиве
|
||||||
|
- Добавлено отображение `case_taxonomy` вместо "Разобрались" на странице отдельного кейса
|
||||||
|
- Изменён файл: `wp-content/themes/clientprav-theme/single.php`
|
||||||
|
|
||||||
|
**Изменения:**
|
||||||
|
```php
|
||||||
|
// Для кейсов используем case_taxonomy вместо названия категории
|
||||||
|
if (has_category('cases')) {
|
||||||
|
$case_taxonomy = clientprav_get_case_taxonomy(get_the_ID());
|
||||||
|
if (!empty($case_taxonomy)) {
|
||||||
|
$category_name = $case_taxonomy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Обсуждение форм в WordPress
|
||||||
|
|
||||||
|
**Варианты интеграции форм:**
|
||||||
|
1. **REST API WordPress** - форма отправляет данные на WordPress API
|
||||||
|
2. **Отправка на внешний сервер/API** - форма отправляет на n8n webhook
|
||||||
|
3. **Встроенный React-компонент** - форма собирается в JS файл и встраивается в WordPress
|
||||||
|
|
||||||
|
**Текущее решение:** iframe с формой на `aiform.clientright.ru`
|
||||||
|
|
||||||
|
### 3. Интеграция React формы из Docker
|
||||||
|
|
||||||
|
**Найденная структура:**
|
||||||
|
- Путь к форме: `/var/www/fastuser/data/www/crm.clientright.ru/ticket_form/frontend/`
|
||||||
|
- Сборщик: Vite
|
||||||
|
- Технологии: React 18.3.1, TypeScript, Ant Design 5.21.6
|
||||||
|
- Контейнер: `ticket_form_frontend_prod` (порт 5176)
|
||||||
|
|
||||||
|
**План перехода на встроенный компонент:**
|
||||||
|
1. Создать точку входа `src/wordpress-entry.tsx`
|
||||||
|
2. Настроить Vite для сборки библиотеки
|
||||||
|
3. Собрать форму: `npm run build`
|
||||||
|
4. Скопировать в WordPress: `dist/ticket-form.js` → `wp-content/themes/clientprav-theme/assets/js/`
|
||||||
|
5. Подключить через `functions.php` с шорткодом `[ticket_form]`
|
||||||
|
6. Настроить API-прокси через WordPress REST API
|
||||||
|
|
||||||
|
**Важные моменты:**
|
||||||
|
- Размер файла может быть 2-5 MB (с Ant Design)
|
||||||
|
- Нужен CSS Ant Design через CDN
|
||||||
|
- Backend API на порту 8200
|
||||||
|
- Зависимости: React, ReactDOM, Ant Design
|
||||||
|
|
||||||
|
**Рекомендация:** Для сложной формы лучше оставить iframe (проще поддерживать, изоляция)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Изменённые файлы
|
||||||
|
|
||||||
|
### 1. `wp-content/themes/clientprav-theme/single.php`
|
||||||
|
- Добавлено отображение `case_taxonomy` для кейсов вместо названия категории
|
||||||
|
|
||||||
|
### 2. `wp-content/themes/clientprav-theme/page-form.php`
|
||||||
|
- Улучшена интеграция iframe с обработкой событий:
|
||||||
|
- Автоматическая высота iframe
|
||||||
|
- Обработка успешной отправки формы
|
||||||
|
- Обработка ошибок
|
||||||
|
- Отслеживание прогресса
|
||||||
|
|
||||||
|
### 3. Создан пример React формы
|
||||||
|
- `react-form-example/` - пример простой формы для WordPress
|
||||||
|
- Включает: структуру проекта, webpack.config.js, пример компонента
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Следующие шаги
|
||||||
|
|
||||||
|
1. **Решение по форме:**
|
||||||
|
- Оставить iframe (текущее решение)
|
||||||
|
- Или перейти на встроенный React компонент
|
||||||
|
|
||||||
|
2. **Если переходить на встроенный компонент:**
|
||||||
|
- Настроить сборку Vite для библиотеки
|
||||||
|
- Создать точку входа для WordPress
|
||||||
|
- Настроить API-прокси
|
||||||
|
- Протестировать интеграцию
|
||||||
|
|
||||||
|
3. **Улучшения iframe (если оставляем):**
|
||||||
|
- Добавить уведомления после отправки
|
||||||
|
- Интеграция с Google Analytics
|
||||||
|
- Сохранение данных в WordPress
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Полезные ссылки
|
||||||
|
|
||||||
|
- Форма: https://aiform.clientright.ru/
|
||||||
|
- Docker контейнер: `ticket_form_frontend_prod`
|
||||||
|
- Путь к коду: `/var/www/fastuser/data/www/crm.clientright.ru/ticket_form/frontend/`
|
||||||
|
- Docker compose: `/var/www/fastuser/data/www/crm.clientright.ru/ticket_form/docker-compose.yml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Технические детали
|
||||||
|
|
||||||
|
**Структура формы:**
|
||||||
|
```
|
||||||
|
frontend/
|
||||||
|
├── src/
|
||||||
|
│ ├── pages/
|
||||||
|
│ │ └── ClaimForm.tsx # Основной компонент формы
|
||||||
|
│ ├── components/
|
||||||
|
│ │ └── form/ # Компоненты шагов формы
|
||||||
|
│ ├── api/ # API запросы
|
||||||
|
│ └── utils/ # Утилиты
|
||||||
|
├── vite.config.ts # Конфигурация Vite
|
||||||
|
└── package.json # Зависимости
|
||||||
|
```
|
||||||
|
|
||||||
|
**Зависимости формы:**
|
||||||
|
- react: ^18.3.1
|
||||||
|
- react-dom: ^18.3.1
|
||||||
|
- antd: ^5.21.6
|
||||||
|
- @ant-design/icons: ^5.5.1
|
||||||
|
- axios: ^1.7.7
|
||||||
|
- @tanstack/react-query: ^5.59.16
|
||||||
|
- zustand: ^5.0.1
|
||||||
|
- socket.io-client: ^4.8.1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Конец лога**
|
||||||
|
|
||||||
170
wp-content/themes/clientprav-theme/page-form.php
Normal file
170
wp-content/themes/clientprav-theme/page-form.php
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Template Name: Страница с формой
|
||||||
|
* Template Post Type: page
|
||||||
|
*
|
||||||
|
* Шаблон страницы с формой обратной связи
|
||||||
|
*
|
||||||
|
* @package Clientprav
|
||||||
|
*/
|
||||||
|
|
||||||
|
get_header();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="min-h-screen bg-gray-50 pt-24 pb-16">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<!-- Навигация назад -->
|
||||||
|
<a href="<?php echo esc_url(home_url('/')); ?>"
|
||||||
|
class="text-gray-600 hover:text-gray-900 mb-8 inline-flex items-center gap-2 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
||||||
|
</svg>
|
||||||
|
Назад на главную
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Заголовок -->
|
||||||
|
<div class="mb-8">
|
||||||
|
<h1 class="text-5xl text-gray-900 mb-4">Получить помощь</h1>
|
||||||
|
<p class="text-xl text-gray-600">
|
||||||
|
Заполните форму, и мы поможем защитить ваши права бесплатно
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Форма в iframe -->
|
||||||
|
<div class="bg-white rounded-2xl shadow-lg overflow-hidden">
|
||||||
|
<div class="form-iframe-wrapper">
|
||||||
|
<iframe
|
||||||
|
id="aiform-iframe"
|
||||||
|
src="https://aiform.clientright.ru/"
|
||||||
|
frameborder="0"
|
||||||
|
scrolling="yes"
|
||||||
|
allow="camera; microphone; geolocation"
|
||||||
|
class="w-full border-0"
|
||||||
|
style="min-height: 800px; height: 100vh; max-height: 1200px;">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Адаптивные стили для iframe */
|
||||||
|
.form-iframe-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 800px;
|
||||||
|
height: 100vh;
|
||||||
|
max-height: 1200px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#aiform-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Адаптация для мобильных устройств */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.form-iframe-wrapper {
|
||||||
|
min-height: 600px;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#aiform-iframe {
|
||||||
|
min-height: 600px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Для очень маленьких экранов */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.form-iframe-wrapper {
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#aiform-iframe {
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Улучшенная интеграция с формой через postMessage
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
// Проверяем источник сообщения
|
||||||
|
if (event.origin !== 'https://aiform.clientright.ru') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const iframe = document.getElementById('aiform-iframe');
|
||||||
|
const data = event.data;
|
||||||
|
|
||||||
|
// Автоматическая высота iframe
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
|
// Изменение высоты
|
||||||
|
if (data.type === 'resize' && data.height) {
|
||||||
|
if (iframe) {
|
||||||
|
iframe.style.height = data.height + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форма отправлена успешно
|
||||||
|
if (data.type === 'form-submitted' || data.type === 'submit-success') {
|
||||||
|
console.log('Форма отправлена:', data);
|
||||||
|
|
||||||
|
// Можно отправить событие в Google Analytics, если нужно
|
||||||
|
if (typeof gtag !== 'undefined') {
|
||||||
|
gtag('event', 'form_submit', {
|
||||||
|
'event_category': 'Form',
|
||||||
|
'event_label': 'AI Form'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Можно показать уведомление на странице WordPress
|
||||||
|
// showNotification('Спасибо! Ваша заявка отправлена.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ошибка при отправке
|
||||||
|
if (data.type === 'form-error' || data.type === 'submit-error') {
|
||||||
|
console.error('Ошибка формы:', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Прогресс заполнения формы
|
||||||
|
if (data.type === 'form-progress') {
|
||||||
|
// Можно показать прогресс-бар, если нужно
|
||||||
|
// updateProgressBar(data.progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Улучшенная обработка загрузки iframe
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const iframe = document.getElementById('aiform-iframe');
|
||||||
|
|
||||||
|
if (!iframe) return;
|
||||||
|
|
||||||
|
// Обработка загрузки iframe
|
||||||
|
iframe.addEventListener('load', function() {
|
||||||
|
// Пытаемся установить связь с формой
|
||||||
|
try {
|
||||||
|
// Запрашиваем начальную высоту
|
||||||
|
iframe.contentWindow.postMessage({
|
||||||
|
type: 'get-height'
|
||||||
|
}, 'https://aiform.clientright.ru');
|
||||||
|
} catch (e) {
|
||||||
|
// Игнорируем ошибки CORS
|
||||||
|
console.warn('Не удалось установить связь с формой:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработка ошибок загрузки
|
||||||
|
iframe.addEventListener('error', function() {
|
||||||
|
console.error('Ошибка загрузки формы');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
get_footer();
|
||||||
|
|
||||||
381
wp-content/themes/clientprav-theme/single.php
Normal file
381
wp-content/themes/clientprav-theme/single.php
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Шаблон одиночной записи
|
||||||
|
*
|
||||||
|
* @package Clientprav
|
||||||
|
*/
|
||||||
|
|
||||||
|
get_header();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="min-h-screen bg-gray-50 pt-24 pb-16">
|
||||||
|
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||||
|
<!-- Навигация назад -->
|
||||||
|
<?php
|
||||||
|
$categories = get_the_category();
|
||||||
|
$category_slug = !empty($categories) ? $categories[0]->slug : '';
|
||||||
|
if ($category_slug) :
|
||||||
|
?>
|
||||||
|
<a href="<?php echo esc_url(clientprav_get_category_link($category_slug)); ?>"
|
||||||
|
class="text-gray-600 hover:text-gray-900 mb-8 inline-flex items-center gap-2 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
||||||
|
</svg>
|
||||||
|
Назад к списку
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<article id="post-<?php the_ID(); ?>" <?php post_class('max-w-4xl mx-auto'); ?>>
|
||||||
|
<header class="mb-8">
|
||||||
|
<!-- Категория Badge -->
|
||||||
|
<?php
|
||||||
|
$categories = get_the_category();
|
||||||
|
$category_name = !empty($categories) ? $categories[0]->name : '';
|
||||||
|
|
||||||
|
// Для кейсов используем case_taxonomy вместо названия категории
|
||||||
|
if (has_category('cases')) {
|
||||||
|
$case_taxonomy = clientprav_get_case_taxonomy(get_the_ID());
|
||||||
|
if (!empty($case_taxonomy)) {
|
||||||
|
$category_name = $case_taxonomy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($category_name)) :
|
||||||
|
?>
|
||||||
|
<div class="mb-4">
|
||||||
|
<span class="text-sm <?php echo has_category('cases') ? 'bg-blue-100 text-blue-700' : 'bg-blue-50 text-blue-600'; ?> px-4 py-1.5 rounded-full">
|
||||||
|
<?php echo esc_html($category_name); ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h1 class="text-5xl text-gray-900 mb-6 leading-tight">
|
||||||
|
<?php the_title(); ?>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<!-- Мета-информация -->
|
||||||
|
<?php if (has_category('news')) : ?>
|
||||||
|
<div class="flex items-center justify-between mb-8 pb-6 border-b border-gray-200">
|
||||||
|
<div class="flex items-center gap-6 text-gray-600">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<span><?php echo get_the_date('d F Y'); ?></span>
|
||||||
|
</div>
|
||||||
|
<div>Автор: <?php the_author(); ?></div>
|
||||||
|
<?php
|
||||||
|
$reading_time = get_post_meta(get_the_ID(), 'reading_time', true);
|
||||||
|
if (empty($reading_time)) {
|
||||||
|
$content = get_the_content();
|
||||||
|
$word_count = str_word_count(strip_tags($content));
|
||||||
|
$reading_time = max(1, round($word_count / 200)); // 200 слов в минуту
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div><?php echo $reading_time; ?> мин чтения</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Кнопка "Поделиться" -->
|
||||||
|
<div class="relative">
|
||||||
|
<button id="share-btn" class="flex items-center gap-2 text-gray-600 hover:text-blue-600 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"></path>
|
||||||
|
</svg>
|
||||||
|
Поделиться
|
||||||
|
</button>
|
||||||
|
<div id="share-menu" class="hidden absolute right-0 mt-2 bg-white border border-gray-200 rounded-xl shadow-lg p-2 min-w-[200px] z-10">
|
||||||
|
<a href="https://www.facebook.com/sharer/sharer.php?u=<?php echo urlencode(get_permalink()); ?>" target="_blank" class="w-full flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-50">
|
||||||
|
<svg class="w-5 h-5 text-blue-600" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
||||||
|
</svg>
|
||||||
|
<span>Facebook</span>
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/intent/tweet?url=<?php echo urlencode(get_permalink()); ?>&text=<?php echo urlencode(get_the_title()); ?>" target="_blank" class="w-full flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-50">
|
||||||
|
<svg class="w-5 h-5 text-sky-500" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
|
||||||
|
</svg>
|
||||||
|
<span>Twitter</span>
|
||||||
|
</a>
|
||||||
|
<a href="mailto:?subject=<?php echo urlencode(get_the_title()); ?>&body=<?php echo urlencode(get_permalink()); ?>" class="w-full flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-50">
|
||||||
|
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Email</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php elseif (has_category('cases')) : ?>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8 py-6 border-y border-gray-200">
|
||||||
|
<div class="flex items-center gap-2 text-gray-600">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Дата решения: <?php echo get_the_date('d F'); ?></span>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
$duration = get_post_meta(get_the_ID(), 'case_duration_days', true);
|
||||||
|
if (empty($duration)) {
|
||||||
|
$duration = get_post_meta(get_the_ID(), 'duration_days', true);
|
||||||
|
}
|
||||||
|
if (!empty($duration)) :
|
||||||
|
?>
|
||||||
|
<div class="flex items-center gap-2 text-gray-600">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Срок: <?php echo esc_html($duration); ?> дней</span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php
|
||||||
|
$result = clientprav_get_case_result(get_the_ID());
|
||||||
|
if (!empty($result)) :
|
||||||
|
?>
|
||||||
|
<div class="flex items-center gap-2 text-green-600">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
|
||||||
|
</svg>
|
||||||
|
<span class="font-semibold"><?php echo esc_html($result); ?></span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php elseif (has_category('faq')) : ?>
|
||||||
|
<div class="flex items-center gap-6 mb-8 pb-6 border-b border-gray-200 text-gray-600">
|
||||||
|
<div>Юрист: <?php the_author(); ?></div>
|
||||||
|
<?php
|
||||||
|
$views = get_post_meta(get_the_ID(), 'faq_views_count', true);
|
||||||
|
if (empty($views)) {
|
||||||
|
$views = get_post_meta(get_the_ID(), 'views_count', true);
|
||||||
|
}
|
||||||
|
if (!empty($views)) :
|
||||||
|
?>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
|
||||||
|
</svg>
|
||||||
|
<span><?php echo number_format($views, 0, ',', ' '); ?> просмотра</span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<div><?php echo get_the_date('d F Y'); ?></div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (has_post_thumbnail()) : ?>
|
||||||
|
<div class="aspect-video rounded-2xl overflow-hidden bg-gray-200 mb-10">
|
||||||
|
<?php the_post_thumbnail('large', array('class' => 'w-full h-full object-cover')); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Контент статьи -->
|
||||||
|
<div class="prose prose-lg max-w-none mb-12">
|
||||||
|
<?php
|
||||||
|
the_content();
|
||||||
|
|
||||||
|
wp_link_pages(array(
|
||||||
|
'before' => '<div class="page-links">' . __('Страницы:', 'clientprav'),
|
||||||
|
'after' => '</div>',
|
||||||
|
));
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (has_category('cases')) : ?>
|
||||||
|
<?php
|
||||||
|
$problem = clientprav_get_case_problem(get_the_ID());
|
||||||
|
$result = clientprav_get_case_result(get_the_ID());
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!-- Ситуация -->
|
||||||
|
<?php if ($problem) : ?>
|
||||||
|
<section class="mb-12">
|
||||||
|
<h2 class="text-3xl text-gray-900 mb-6">Ситуация</h2>
|
||||||
|
<div class="prose prose-lg max-w-none">
|
||||||
|
<?php echo wpautop(esc_html($problem)); ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Решение (временная шкала) -->
|
||||||
|
<?php
|
||||||
|
$timeline = get_post_meta(get_the_ID(), 'case_timeline', true);
|
||||||
|
if (empty($timeline)) {
|
||||||
|
$timeline = get_post_meta(get_the_ID(), 'timeline', true);
|
||||||
|
}
|
||||||
|
if (!empty($timeline) || $problem) :
|
||||||
|
?>
|
||||||
|
<section class="mb-12 bg-gray-50 rounded-2xl p-8">
|
||||||
|
<h2 class="text-3xl text-gray-900 mb-6">Как мы решали</h2>
|
||||||
|
<?php if (!empty($timeline) && is_array($timeline)) : ?>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<?php foreach ($timeline as $index => $item) : ?>
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center">
|
||||||
|
<?php if ($index === count($timeline) - 1) : ?>
|
||||||
|
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||||
|
</svg>
|
||||||
|
<?php else : ?>
|
||||||
|
<div class="w-2 h-2 bg-white rounded-full"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php if ($index !== count($timeline) - 1) : ?>
|
||||||
|
<div class="w-0.5 h-full bg-blue-200 mt-2"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 pb-6">
|
||||||
|
<div class="text-sm text-blue-600 mb-1"><?php echo esc_html($item['date'] ?? ''); ?></div>
|
||||||
|
<div class="text-gray-900"><?php echo esc_html($item['event'] ?? ''); ?></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php else : ?>
|
||||||
|
<div class="prose prose-lg max-w-none">
|
||||||
|
<?php the_content(); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Результат -->
|
||||||
|
<?php if ($result) : ?>
|
||||||
|
<section class="mb-12">
|
||||||
|
<h2 class="text-3xl text-gray-900 mb-6">Результат</h2>
|
||||||
|
<div class="prose prose-lg max-w-none">
|
||||||
|
<div class="bg-green-50 rounded-lg p-4 border-l-4 border-green-600">
|
||||||
|
<p class="text-green-700 font-semibold text-lg"><?php echo esc_html($result); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Документы -->
|
||||||
|
<?php
|
||||||
|
$documents = get_post_meta(get_the_ID(), 'case_documents', true);
|
||||||
|
if (empty($documents)) {
|
||||||
|
$documents = get_post_meta(get_the_ID(), 'documents', true);
|
||||||
|
}
|
||||||
|
if (!empty($documents)) :
|
||||||
|
if (!is_array($documents)) {
|
||||||
|
$documents = explode("\n", $documents);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<section class="mb-12 bg-blue-50 rounded-2xl p-8">
|
||||||
|
<div class="flex items-start gap-4 mb-6">
|
||||||
|
<svg class="w-6 h-6 text-blue-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl text-gray-900 mb-2">Подготовленные документы</h3>
|
||||||
|
<p class="text-gray-600">Все эти документы мы подготовили бесплатно в рамках нашего сервиса</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="space-y-2">
|
||||||
|
<?php foreach ($documents as $doc) : ?>
|
||||||
|
<li class="flex items-center gap-3">
|
||||||
|
<svg class="w-5 h-5 text-green-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||||
|
</svg>
|
||||||
|
<span class="text-gray-700"><?php echo esc_html(trim($doc)); ?></span>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- CTA блок для кейсов (градиент) -->
|
||||||
|
<div class="bg-gradient-to-r from-blue-600 to-blue-700 rounded-2xl p-10 mb-12 text-white text-center">
|
||||||
|
<svg class="w-12 h-12 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3"></path>
|
||||||
|
</svg>
|
||||||
|
<h3 class="text-3xl mb-4">Попали в похожую ситуацию?</h3>
|
||||||
|
<p class="text-xl mb-6 text-blue-100">Мы поможем защитить ваши права бесплатно. Расскажите о своей проблеме, и мы подготовим все необходимые документы.</p>
|
||||||
|
<a href="<?php echo esc_url(clientprav_get_form_url()); ?>"
|
||||||
|
class="inline-block bg-white text-blue-600 px-10 py-4 rounded-lg hover:bg-blue-50 transition-colors font-semibold">
|
||||||
|
Получить помощь
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (has_category('faq')) : ?>
|
||||||
|
<?php
|
||||||
|
$short_answer = clientprav_get_faq_short_answer(get_the_ID());
|
||||||
|
if ($short_answer) :
|
||||||
|
?>
|
||||||
|
<!-- Краткий ответ -->
|
||||||
|
<div class="mb-10 bg-blue-50 border-l-4 border-blue-600 rounded-r-xl p-6">
|
||||||
|
<h3 class="text-xl text-gray-900 mb-3">Краткий ответ</h3>
|
||||||
|
<p class="text-gray-700 leading-relaxed"><?php echo esc_html($short_answer); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- CTA блок для FAQ -->
|
||||||
|
<div class="bg-blue-50 rounded-2xl p-8 mb-12">
|
||||||
|
<h3 class="text-2xl text-gray-900 mb-3">Нужна помощь с защитой прав потребителей?</h3>
|
||||||
|
<p class="text-gray-600 mb-6">Наш сервис бесплатно поможет составить претензию, жалобу или исковое заявление</p>
|
||||||
|
<a href="<?php echo esc_url(clientprav_get_form_url()); ?>"
|
||||||
|
class="inline-block bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||||
|
Получить консультацию
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (has_category('news')) : ?>
|
||||||
|
<!-- CTA блок для новостей -->
|
||||||
|
<div class="bg-blue-50 rounded-2xl p-8 mb-12">
|
||||||
|
<h3 class="text-2xl text-gray-900 mb-3">Нужна помощь с защитой прав потребителей?</h3>
|
||||||
|
<p class="text-gray-600 mb-6">Наш сервис бесплатно поможет составить претензию, жалобу или исковое заявление</p>
|
||||||
|
<a href="<?php echo esc_url(clientprav_get_form_url()); ?>"
|
||||||
|
class="inline-block bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||||
|
Получить консультацию
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Похожие материалы -->
|
||||||
|
<?php
|
||||||
|
$current_categories = wp_get_post_categories(get_the_ID());
|
||||||
|
$related_query = new WP_Query(array(
|
||||||
|
'post_type' => 'post',
|
||||||
|
'posts_per_page' => 3,
|
||||||
|
'post__not_in' => array(get_the_ID()),
|
||||||
|
'category__in' => $current_categories,
|
||||||
|
'orderby' => 'date',
|
||||||
|
'order' => 'DESC',
|
||||||
|
));
|
||||||
|
if ($related_query->have_posts()) :
|
||||||
|
?>
|
||||||
|
<div class="mt-12">
|
||||||
|
<h3 class="text-2xl text-gray-900 mb-6">
|
||||||
|
<?php echo has_category('cases') ? 'Другие кейсы' : (has_category('faq') ? 'Похожие вопросы' : 'Читайте также'); ?>
|
||||||
|
</h3>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
|
||||||
|
<a href="<?php the_permalink(); ?>"
|
||||||
|
class="block bg-gray-50 rounded-xl p-5 hover:bg-gray-100 transition-colors group">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-500 mb-2"><?php echo get_the_date(); ?></div>
|
||||||
|
<div class="text-lg text-gray-900 group-hover:text-blue-600 transition-colors">
|
||||||
|
<?php the_title(); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 text-gray-400 group-hover:text-blue-600 transition-colors rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php wp_reset_postdata(); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
get_footer();
|
||||||
|
|
||||||
Reference in New Issue
Block a user