feat(categories): add options to select what categories to show on front page
This commit is contained in:
@@ -82,6 +82,7 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
$this->load->model('setting/setting');
|
||||
$this->load->model('tool/image');
|
||||
$this->load->model('catalog/product');
|
||||
$this->load->model('catalog/category');
|
||||
$this->load->model('localisation/order_status');
|
||||
$this->load->model('customer/customer_group');
|
||||
}
|
||||
@@ -149,6 +150,17 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
'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])) {
|
||||
$data[$key] = $this->request->post[$key];
|
||||
} else {
|
||||
@@ -326,6 +338,7 @@ TEXT,
|
||||
'module_tgshop_order_customer_group_id' => 1,
|
||||
'module_tgshop_order_default_status_id' => 1,
|
||||
'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/',
|
||||
'module_tgshop_mainpage_categories' => 'latest10'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -438,6 +451,21 @@ HTML,
|
||||
'type' => 'products',
|
||||
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”.',
|
||||
],
|
||||
|
||||
'module_tgshop_mainpage_categories' => [
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'no_categories' => 'Отображать только кнопку "Каталог"',
|
||||
'latest10' => 'Последние 10 категорий',
|
||||
'featured' => 'Избранные категории (задать в поле ниже)',
|
||||
],
|
||||
'help' => 'Выберите, какие категории показывать на главной странице магазина в Telegram. Это влияет на первую видимую секцию каталога для пользователя.',
|
||||
],
|
||||
|
||||
'module_tgshop_featured_categories' => [
|
||||
'type' => 'categories',
|
||||
'help' => 'На главной странице будут отображаться эти категории, если вы выберете этот вариант в настройке “Категории на главной”.',
|
||||
],
|
||||
],
|
||||
|
||||
'orders' => [
|
||||
|
||||
@@ -27,6 +27,8 @@ $_['lbl_module_tgshop_featured_products'] = 'Избранные товары';
|
||||
$_['lbl_module_tgshop_order_customer_group_id'] = 'Группа покупателей';
|
||||
$_['lbl_module_tgshop_order_default_status_id'] = 'Статус заказов';
|
||||
$_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App';
|
||||
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
|
||||
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
||||
|
||||
// Entry
|
||||
$_['entry_status'] = 'Статус';
|
||||
|
||||
@@ -144,6 +144,43 @@
|
||||
});
|
||||
</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 #}
|
||||
{% elseif item['type'] == 'chatid' %}
|
||||
{% if module_tgshop_bot_token %}
|
||||
|
||||
@@ -59,6 +59,8 @@ class ControllerExtensionTgshopHandle extends Controller
|
||||
'theme_dark' => $this->config->get('module_tgshop_theme_dark'),
|
||||
'mainpage_products' => $this->config->get('module_tgshop_mainpage_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,
|
||||
'ya_metrika_enabled' => ! empty(trim($this->config->get('module_tgshop_yandex_metrika'))),
|
||||
'telegram' => [
|
||||
|
||||
@@ -4,7 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
@@ -15,17 +17,28 @@ class CategoriesHandler
|
||||
|
||||
private Builder $queryBuilder;
|
||||
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->ocImageTool = $ocImageTool;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
public function index(): JsonResponse
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$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()
|
||||
->select([
|
||||
'categories.category_id' => 'id',
|
||||
@@ -43,12 +56,20 @@ class CategoriesHandler
|
||||
}
|
||||
)
|
||||
->where('categories.status', '=', 1)
|
||||
->when(
|
||||
$forMainPage && $mainpageCategories === 'featured' && $featuredCategories,
|
||||
function (Builder $query) use ($featuredCategories) {
|
||||
$query->whereIn('categories.category_id', $featuredCategories);
|
||||
}
|
||||
)
|
||||
->orderBy('parent_id')
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
|
||||
$categories = $this->buildCategoryTree($categoriesFlat);
|
||||
|
||||
$categories = array_slice($categories, 0, $perPage);
|
||||
|
||||
return new JsonResponse([
|
||||
'data' => array_map(static function ($category) {
|
||||
return [
|
||||
|
||||
@@ -27,7 +27,7 @@ export const useCategoriesStore = defineStore('categories', {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const response = await ftch('categoriesList', {
|
||||
perPage: 7,
|
||||
forMainPage: true,
|
||||
});
|
||||
this.topCategories = response.data;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user