feat(product): add option to disable store feature
This commit is contained in:
@@ -31,6 +31,7 @@ if (is_readable($sysLibPath . '/oc_telegram_shop.phar')) {
|
|||||||
* @property ModelCustomerCustomerGroup $model_customer_customer_group
|
* @property ModelCustomerCustomerGroup $model_customer_customer_group
|
||||||
* @property ModelLocalisationOrderStatus $model_localisation_order_status
|
* @property ModelLocalisationOrderStatus $model_localisation_order_status
|
||||||
* @property DB $db
|
* @property DB $db
|
||||||
|
* @property Log $log
|
||||||
*/
|
*/
|
||||||
class ControllerExtensionModuleTgshop extends Controller
|
class ControllerExtensionModuleTgshop extends Controller
|
||||||
{
|
{
|
||||||
@@ -342,11 +343,11 @@ TEXT,
|
|||||||
'module_tgshop_theme_light' => 'light',
|
'module_tgshop_theme_light' => 'light',
|
||||||
'module_tgshop_theme_dark' => 'dark',
|
'module_tgshop_theme_dark' => 'dark',
|
||||||
'module_tgshop_mainpage_products' => 'most_viewed',
|
'module_tgshop_mainpage_products' => 'most_viewed',
|
||||||
'module_tgshop_featured_products' => [],
|
|
||||||
'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'
|
'module_tgshop_mainpage_categories' => 'latest10',
|
||||||
|
'module_tgshop_enable_store' => 1,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +446,17 @@ HTML,
|
|||||||
],
|
],
|
||||||
|
|
||||||
'shop' => [
|
'shop' => [
|
||||||
|
'module_tgshop_enable_store' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'options' => [
|
||||||
|
0 => 'Выключено',
|
||||||
|
1 => 'Включено',
|
||||||
|
],
|
||||||
|
'help' => <<<HTML
|
||||||
|
Если опция <strong>включена</strong> — пользователи смогут оформлять заказы прямо в Telegram-магазине. <br>
|
||||||
|
Если <strong>выключена</strong> — оформление заказов будет недоступно. Вместо кнопки «Добавить в корзину» пользователи увидят кнопку «Перейти к товару», которая откроет страницу товара на вашем сайте. В этом режиме Telecart работает как каталог.
|
||||||
|
HTML,
|
||||||
|
],
|
||||||
'module_tgshop_mainpage_products' => [
|
'module_tgshop_mainpage_products' => [
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'options' => [
|
'options' => [
|
||||||
@@ -457,7 +469,7 @@ HTML,
|
|||||||
|
|
||||||
'module_tgshop_featured_products' => [
|
'module_tgshop_featured_products' => [
|
||||||
'type' => 'products',
|
'type' => 'products',
|
||||||
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”.',
|
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”. Если товары не выбраны, то будут показаны популярные товары.',
|
||||||
],
|
],
|
||||||
|
|
||||||
'module_tgshop_mainpage_categories' => [
|
'module_tgshop_mainpage_categories' => [
|
||||||
@@ -522,7 +534,7 @@ HTML,
|
|||||||
|
|
||||||
$diff = [];
|
$diff = [];
|
||||||
foreach ($defaults as $key => $value) {
|
foreach ($defaults as $key => $value) {
|
||||||
if (! isset($settings[$key])) {
|
if (! array_key_exists($key, $settings)) {
|
||||||
$diff[$key] = $defaults[$key];
|
$diff[$key] = $defaults[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,6 +542,15 @@ HTML,
|
|||||||
if ($diff) {
|
if ($diff) {
|
||||||
$settings = array_merge($settings, $diff);
|
$settings = array_merge($settings, $diff);
|
||||||
$this->model_setting_setting->editSetting('module_tgshop', $settings);
|
$this->model_setting_setting->editSetting('module_tgshop', $settings);
|
||||||
|
$this->log->write('[TELECART] Выполнено обновление настроек по умолчанию для модуля.');
|
||||||
|
$this->session->data['success'] = 'Выполнено обновление настроек по умолчанию для модуля.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function install(): void
|
||||||
|
{
|
||||||
|
$this->log->write('[TELECART] Запуск установки модуля.');
|
||||||
|
$this->updateConfigFromDefaults();
|
||||||
|
$this->log->write('[TELECART] Установка модуля завершена.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ $_['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_mainpage_categories'] = 'Категории на главной';
|
||||||
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
||||||
|
$_['lbl_module_tgshop_enable_store'] = 'Разрешить покупки';
|
||||||
|
|
||||||
// Entry
|
// Entry
|
||||||
$_['entry_status'] = 'Статус';
|
$_['entry_status'] = 'Статус';
|
||||||
|
|||||||
@@ -58,9 +58,10 @@ class ControllerExtensionTgshopHandle extends Controller
|
|||||||
'theme_light' => $this->config->get('module_tgshop_theme_light'),
|
'theme_light' => $this->config->get('module_tgshop_theme_light'),
|
||||||
'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' => (array) $this->config->get('module_tgshop_featured_products'),
|
||||||
'mainpage_categories' => $this->config->get('module_tgshop_mainpage_categories'),
|
'mainpage_categories' => $this->config->get('module_tgshop_mainpage_categories'),
|
||||||
'featured_categories' => $this->config->get('module_tgshop_featured_categories'),
|
'featured_categories' => (array) $this->config->get('module_tgshop_featured_categories'),
|
||||||
|
'store_enabled' => filter_var($this->config->get('module_tgshop_enable_store'), FILTER_VALIDATE_BOOLEAN),
|
||||||
'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' => [
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class SettingsHandler
|
|||||||
'theme_dark' => $this->settings->get('theme_dark'),
|
'theme_dark' => $this->settings->get('theme_dark'),
|
||||||
'ya_metrika_enabled' => $this->settings->get('ya_metrika_enabled'),
|
'ya_metrika_enabled' => $this->settings->get('ya_metrika_enabled'),
|
||||||
'app_enabled' => $this->settings->get('app_enabled'),
|
'app_enabled' => $this->settings->get('app_enabled'),
|
||||||
|
'store_enabled' => $this->settings->get('store_enabled'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class ProductsService
|
|||||||
->value('name');
|
->value('name');
|
||||||
}
|
}
|
||||||
|
|
||||||
$customerGroupId = (int)$this->oc->config->get('config_customer_group_id');
|
$customerGroupId = (int) $this->oc->config->get('config_customer_group_id');
|
||||||
$specialPriceSql = "(SELECT price
|
$specialPriceSql = "(SELECT price
|
||||||
FROM oc_product_special ps
|
FROM oc_product_special ps
|
||||||
WHERE ps.product_id = products.product_id
|
WHERE ps.product_id = products.product_id
|
||||||
@@ -245,6 +245,11 @@ class ProductsService
|
|||||||
$data['reward'] = $product_info['reward'];
|
$data['reward'] = $product_info['reward'];
|
||||||
$data['points'] = (int) $product_info['points'];
|
$data['points'] = (int) $product_info['points'];
|
||||||
$data['description'] = html_entity_decode($product_info['description'], ENT_QUOTES, 'UTF-8');
|
$data['description'] = html_entity_decode($product_info['description'], ENT_QUOTES, 'UTF-8');
|
||||||
|
$data['share'] = html_entity_decode(
|
||||||
|
$this->oc->url->link('product/product', 'product_id=' . $productId),
|
||||||
|
ENT_QUOTES | ENT_HTML5,
|
||||||
|
'UTF-8'
|
||||||
|
);
|
||||||
|
|
||||||
if ($product_info['quantity'] <= 0) {
|
if ($product_info['quantity'] <= 0) {
|
||||||
$data['stock'] = $product_info['stock_status'];
|
$data['stock'] = $product_info['stock_status'];
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<component :is="Component" :key="route.fullPath" />
|
<component :is="Component" :key="route.fullPath" />
|
||||||
</Transition>
|
</Transition>
|
||||||
</RouterView>
|
</RouterView>
|
||||||
<CartButton/>
|
<CartButton v-if="settings.store_enabled"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ import {useWebAppViewport, useBackButton} from 'vue-tg';
|
|||||||
import {useMiniApp, FullscreenViewport} from 'vue-tg';
|
import {useMiniApp, FullscreenViewport} from 'vue-tg';
|
||||||
import {useRoute, useRouter} from "vue-router";
|
import {useRoute, useRouter} from "vue-router";
|
||||||
import CartButton from "@/components/CartButton.vue";
|
import CartButton from "@/components/CartButton.vue";
|
||||||
|
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
||||||
|
|
||||||
const tg = useMiniApp();
|
const tg = useMiniApp();
|
||||||
const platform = ref();
|
const platform = ref();
|
||||||
@@ -26,6 +27,7 @@ disableVerticalSwipes();
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.name,
|
() => route.name,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {fetchSettings} from "@/utils/ftch.js";
|
|||||||
export const useSettingsStore = defineStore('settings', {
|
export const useSettingsStore = defineStore('settings', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
app_enabled: true,
|
app_enabled: true,
|
||||||
|
store_enabled: true,
|
||||||
app_name: 'OpenCart Telegram магазин',
|
app_name: 'OpenCart Telegram магазин',
|
||||||
app_icon: '',
|
app_icon: '',
|
||||||
app_icon192: '',
|
app_icon192: '',
|
||||||
@@ -38,6 +39,7 @@ export const useSettingsStore = defineStore('settings', {
|
|||||||
this.theme.dark = settings.theme_dark;
|
this.theme.dark = settings.theme_dark;
|
||||||
this.ya_metrika_enabled = settings.ya_metrika_enabled;
|
this.ya_metrika_enabled = settings.ya_metrika_enabled;
|
||||||
this.app_enabled = settings.app_enabled;
|
this.app_enabled = settings.app_enabled;
|
||||||
|
this.store_enabled = settings.store_enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,34 +91,54 @@
|
|||||||
|
|
||||||
<div v-if="product.product_id"
|
<div v-if="product.product_id"
|
||||||
class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex flex-col gap-2 border-t-1 border-t-base-300">
|
class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex flex-col gap-2 border-t-1 border-t-base-300">
|
||||||
<div class="text-error">
|
<template v-if="settings.store_enabled">
|
||||||
{{ error }}
|
<div class="text-error">
|
||||||
</div>
|
{{ error }}
|
||||||
|
|
||||||
<div v-if="canAddToCart === false" class="text-error text-center text-xs mt-1">
|
|
||||||
Выберите обязательные опции
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<div class="flex-1">
|
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-lg w-full"
|
|
||||||
:class="isInCart ? 'btn-success' : 'btn-primary'"
|
|
||||||
:disabled="cart.isLoading || canAddToCart === false"
|
|
||||||
@click="actionBtnClick"
|
|
||||||
>
|
|
||||||
<span v-if="cart.isLoading" class="loading loading-spinner loading-sm"></span>
|
|
||||||
{{ btnText }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Quantity
|
<div v-if="canAddToCart === false" class="text-error text-center text-xs mt-1">
|
||||||
v-if="isInCart === false"
|
Выберите обязательные опции
|
||||||
:modelValue="quantity"
|
</div>
|
||||||
@update:modelValue="setQuantity"
|
|
||||||
size="lg"
|
<div class="flex gap-2">
|
||||||
/>
|
<div class="flex-1">
|
||||||
</div>
|
<button
|
||||||
|
class="btn btn-primary btn-lg w-full"
|
||||||
|
:class="isInCart ? 'btn-success' : 'btn-primary'"
|
||||||
|
:disabled="cart.isLoading || canAddToCart === false"
|
||||||
|
@click="actionBtnClick"
|
||||||
|
>
|
||||||
|
<span v-if="cart.isLoading" class="loading loading-spinner loading-sm"></span>
|
||||||
|
{{ btnText }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Quantity
|
||||||
|
v-if="isInCart === false"
|
||||||
|
:modelValue="quantity"
|
||||||
|
@update:modelValue="setQuantity"
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary btn-lg w-full"
|
||||||
|
:disabled="! product.share"
|
||||||
|
@click="openProductInMarketplace"
|
||||||
|
>
|
||||||
|
<template v-if="product.share">
|
||||||
|
Открыть товар
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template>Товар недоступен</template>
|
||||||
|
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ProductNotFound v-else/>
|
<ProductNotFound v-else/>
|
||||||
@@ -144,6 +164,7 @@ import {apiFetch} from "@/utils/ftch.js";
|
|||||||
import FullScreenImageViewer from "@/components/FullScreenImageViewer.vue";
|
import FullScreenImageViewer from "@/components/FullScreenImageViewer.vue";
|
||||||
import LoadingFullScreen from "@/components/LoadingFullScreen.vue";
|
import LoadingFullScreen from "@/components/LoadingFullScreen.vue";
|
||||||
import ProductNotFound from "@/components/ProductNotFound.vue";
|
import ProductNotFound from "@/components/ProductNotFound.vue";
|
||||||
|
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const productId = computed(() => route.params.id);
|
const productId = computed(() => route.params.id);
|
||||||
@@ -157,6 +178,7 @@ const btnText = computed(() => isInCart.value ? 'В корзине' : 'Купи
|
|||||||
const isFullScreen = ref(false);
|
const isFullScreen = ref(false);
|
||||||
const initialFullScreenIndex = ref(0);
|
const initialFullScreenIndex = ref(0);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
const canAddToCart = computed(() => {
|
const canAddToCart = computed(() => {
|
||||||
if (!product.value || product.value.options === undefined || product.value.options?.length === 0) {
|
if (!product.value || product.value.options === undefined || product.value.options?.length === 0) {
|
||||||
@@ -204,6 +226,14 @@ async function actionBtnClick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openProductInMarketplace() {
|
||||||
|
if (! product.value.share) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Telegram.WebApp.openLink(product.value.share, { try_instant_view: false });
|
||||||
|
}
|
||||||
|
|
||||||
function setQuantity(newQuantity) {
|
function setQuantity(newQuantity) {
|
||||||
quantity.value = newQuantity;
|
quantity.value = newQuantity;
|
||||||
window.Telegram.WebApp.HapticFeedback.selectionChanged();
|
window.Telegram.WebApp.HapticFeedback.selectionChanged();
|
||||||
|
|||||||
Reference in New Issue
Block a user