feat(categories): add options to select what categories to show on front page

This commit is contained in:
2025-09-24 14:02:13 +03:00
parent 490cbfacf7
commit 9e4022f648
6 changed files with 93 additions and 3 deletions

View File

@@ -82,6 +82,7 @@ class ControllerExtensionModuleTgshop extends Controller
$this->load->model('setting/setting'); $this->load->model('setting/setting');
$this->load->model('tool/image'); $this->load->model('tool/image');
$this->load->model('catalog/product'); $this->load->model('catalog/product');
$this->load->model('catalog/category');
$this->load->model('localisation/order_status'); $this->load->model('localisation/order_status');
$this->load->model('customer/customer_group'); $this->load->model('customer/customer_group');
} }
@@ -149,6 +150,17 @@ class ControllerExtensionModuleTgshop extends Controller
'name' => $productItem['name'], 'name' => $productItem['name'],
]; ];
} }
} elseif ($config['type'] === 'categories') {
$categories = $this->request->post[$key] ?? $this->config->get($key) ?? [];
$data[$key] = [];
foreach ($categories as $categoryId) {
$categoryItem = $this->model_catalog_category->getCategory($categoryId);
$data[$key][] = [
'category_id' => $categoryId,
'name' => $categoryItem['name'],
];
}
} elseif (isset($this->request->post[$key])) { } elseif (isset($this->request->post[$key])) {
$data[$key] = $this->request->post[$key]; $data[$key] = $this->request->post[$key];
} else { } else {
@@ -326,6 +338,7 @@ TEXT,
'module_tgshop_order_customer_group_id' => 1, 'module_tgshop_order_customer_group_id' => 1,
'module_tgshop_order_default_status_id' => 1, 'module_tgshop_order_default_status_id' => 1,
'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/', 'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/',
'module_tgshop_mainpage_categories' => 'latest10'
]; ];
} }
@@ -438,6 +451,21 @@ HTML,
'type' => 'products', 'type' => 'products',
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”.', 'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”.',
], ],
'module_tgshop_mainpage_categories' => [
'type' => 'select',
'options' => [
'no_categories' => 'Отображать только кнопку "Каталог"',
'latest10' => 'Последние 10 категорий',
'featured' => 'Избранные категории (задать в поле ниже)',
],
'help' => 'Выберите, какие категории показывать на главной странице магазина в Telegram. Это влияет на первую видимую секцию каталога для пользователя.',
],
'module_tgshop_featured_categories' => [
'type' => 'categories',
'help' => 'На главной странице будут отображаться эти категории, если вы выберете этот вариант в настройке “Категории на главной”.',
],
], ],
'orders' => [ 'orders' => [

View File

@@ -27,6 +27,8 @@ $_['lbl_module_tgshop_featured_products'] = 'Избранные товары';
$_['lbl_module_tgshop_order_customer_group_id'] = 'Группа покупателей'; $_['lbl_module_tgshop_order_customer_group_id'] = 'Группа покупателей';
$_['lbl_module_tgshop_order_default_status_id'] = 'Статус заказов'; $_['lbl_module_tgshop_order_default_status_id'] = 'Статус заказов';
$_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App'; $_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App';
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
// Entry // Entry
$_['entry_status'] = 'Статус'; $_['entry_status'] = 'Статус';

View File

@@ -144,6 +144,43 @@
}); });
</script> </script>
{% elseif item['type'] == 'categories' %}
<input type="text" value="" placeholder="Начните вводить название категории..." id="{{ settingKey }}-input" class="form-control"/>
<div id="{{ settingKey }}-list" class="well well-sm" style="height: 150px; overflow: auto;">
{% for category in attribute(_context, settingKey) %}
<div id="{{ settingKey }}-{{ category.category_id }}">
<i class="fa fa-minus-circle"></i> {{ category.name }}
<input type="hidden" name="{{ settingKey }}[]" value="{{ category.category_id }}"/>
</div>
{% endfor %}
</div>
<script>
$('#{{ settingKey }}-input').autocomplete({
'source': function(request, response) {
$.ajax({
url: 'index.php?route=catalog/category/autocomplete&user_token={{ user_token }}&filter_name=' + encodeURIComponent(request),
dataType: 'json',
success: function(json) {
response($.map(json, function(item) {
return {
label: item['name'],
value: item['category_id']
}
}));
}
});
},
'select': function(item) {
$('#{{ settingKey }}').val('');
$('#{{ settingKey }}-' + item['value']).remove();
$('#{{ settingKey }}-list').append('<div id="{{ settingKey }}-' + item['value'] + '"><i class="fa fa-minus-circle"></i> ' + item['label'] + '<input type="hidden" name="{{ settingKey }}[]" value="' + item['value'] + '" /></div>');
}
});
$('#{{ settingKey }}-list').delegate('.fa-minus-circle', 'click', function() {
$(this).parent().remove();
});
</script>
{# ChatID #} {# ChatID #}
{% elseif item['type'] == 'chatid' %} {% elseif item['type'] == 'chatid' %}
{% if module_tgshop_bot_token %} {% if module_tgshop_bot_token %}

View File

@@ -59,6 +59,8 @@ class ControllerExtensionTgshopHandle extends Controller
'theme_dark' => $this->config->get('module_tgshop_theme_dark'), 'theme_dark' => $this->config->get('module_tgshop_theme_dark'),
'mainpage_products' => $this->config->get('module_tgshop_mainpage_products'), 'mainpage_products' => $this->config->get('module_tgshop_mainpage_products'),
'featured_products' => $this->config->get('module_tgshop_featured_products'), 'featured_products' => $this->config->get('module_tgshop_featured_products'),
'mainpage_categories' => $this->config->get('module_tgshop_mainpage_categories'),
'featured_categories' => $this->config->get('module_tgshop_featured_categories'),
'base_url' => HTTPS_SERVER, 'base_url' => HTTPS_SERVER,
'ya_metrika_enabled' => ! empty(trim($this->config->get('module_tgshop_yandex_metrika'))), 'ya_metrika_enabled' => ! empty(trim($this->config->get('module_tgshop_yandex_metrika'))),
'telegram' => [ 'telegram' => [

View File

@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace App\Handlers; namespace App\Handlers;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse; use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface; use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder; use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause; use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
@@ -15,17 +17,28 @@ class CategoriesHandler
private Builder $queryBuilder; private Builder $queryBuilder;
private ImageToolInterface $ocImageTool; private ImageToolInterface $ocImageTool;
private Settings $settings;
public function __construct(Builder $queryBuilder, ImageToolInterface $ocImageTool) public function __construct(Builder $queryBuilder, ImageToolInterface $ocImageTool, Settings $settings)
{ {
$this->queryBuilder = $queryBuilder; $this->queryBuilder = $queryBuilder;
$this->ocImageTool = $ocImageTool; $this->ocImageTool = $ocImageTool;
$this->settings = $settings;
} }
public function index(): JsonResponse public function index(Request $request): JsonResponse
{ {
$languageId = 1; $languageId = 1;
$perPage = $request->get('perPage', 10);
$forMainPage = filter_var($request->get('forMainPage', false), FILTER_VALIDATE_BOOLEAN);
$featuredCategories = $this->settings->get('featured_categories');
$mainpageCategories = $this->settings->get('mainpage_categories');
if ($forMainPage && $mainpageCategories === 'no_categories') {
return new JsonResponse(['data' => []]);
}
$categoriesFlat = $this->queryBuilder->newQuery() $categoriesFlat = $this->queryBuilder->newQuery()
->select([ ->select([
'categories.category_id' => 'id', 'categories.category_id' => 'id',
@@ -43,12 +56,20 @@ class CategoriesHandler
} }
) )
->where('categories.status', '=', 1) ->where('categories.status', '=', 1)
->when(
$forMainPage && $mainpageCategories === 'featured' && $featuredCategories,
function (Builder $query) use ($featuredCategories) {
$query->whereIn('categories.category_id', $featuredCategories);
}
)
->orderBy('parent_id') ->orderBy('parent_id')
->orderBy('sort_order') ->orderBy('sort_order')
->get(); ->get();
$categories = $this->buildCategoryTree($categoriesFlat); $categories = $this->buildCategoryTree($categoriesFlat);
$categories = array_slice($categories, 0, $perPage);
return new JsonResponse([ return new JsonResponse([
'data' => array_map(static function ($category) { 'data' => array_map(static function ($category) {
return [ return [

View File

@@ -27,7 +27,7 @@ export const useCategoriesStore = defineStore('categories', {
try { try {
this.isLoading = true; this.isLoading = true;
const response = await ftch('categoriesList', { const response = await ftch('categoriesList', {
perPage: 7, forMainPage: true,
}); });
this.topCategories = response.data; this.topCategories = response.data;
} catch (error) { } catch (error) {