feat: add product interaction mode selector with three scenarios

- Add ItemToggleButton component for 3-way toggle in admin panel
- Add product_interaction_mode setting with options: order, manager, browser
- Add manager_username setting for Telegram manager contact
- Remove store_enabled setting, replaced with product_interaction_mode
- Create migration to automatically migrate store_enabled to product_interaction_mode
- Update Product.vue to handle all three interaction modes
- Update Dock.vue to show cart button only when product_interaction_mode is 'order'
- Rename 'Магазин' tab to 'Витрина' in admin panel
- Remove 'Разрешить покупки' option (now controlled via product_interaction_mode)
- Set default product_interaction_mode to 'browser'
- Update StoreDTO to remove enableStore field
- Update SettingsHandler to return product_interaction_mode instead of store_enabled
This commit is contained in:
2025-12-25 18:02:38 +03:00
parent 22ddc3043d
commit ecf4df363d
13 changed files with 228 additions and 29 deletions

View File

@@ -45,7 +45,7 @@
</RouterLink>
<RouterLink
v-if="settings.store_enabled"
v-if="settings.product_interaction_mode === 'order'"
:to="{name: 'cart'}"
:class="{'dock-active': route.name === 'cart'}"
@click="onDockItemClick"

View File

@@ -5,7 +5,8 @@ export const useSettingsStore = defineStore('settings', {
state: () => ({
app_enabled: true,
app_debug: false,
store_enabled: true,
product_interaction_mode: 'browser',
manager_username: null,
app_name: 'OpenCart Telegram магазин',
app_icon: '',
night_auto: true,
@@ -41,7 +42,8 @@ export const useSettingsStore = defineStore('settings', {
this.ya_metrika_enabled = settings.ya_metrika_enabled;
this.app_enabled = settings.app_enabled;
this.app_debug = settings.app_debug;
this.store_enabled = settings.store_enabled;
this.product_interaction_mode = settings.product_interaction_mode ?? 'browser';
this.manager_username = settings.manager_username;
this.feature_coupons = settings.feature_coupons;
this.feature_vouchers = settings.feature_vouchers;
this.show_category_products_button = settings.show_category_products_button ?? true;

View File

@@ -123,7 +123,8 @@
<div v-if="product.product_id"
class="fixed bottom-fix px-4 pb-4 pt-4 left-0 w-full bg-base-100/95 backdrop-blur-md z-50 flex flex-col gap-3 border-t border-base-300 shadow-lg"
>
<template v-if="settings.store_enabled">
<!-- Режим: Создание заказа -->
<template v-if="settings.product_interaction_mode === 'order'">
<div v-if="error" class="alert alert-error alert-sm py-2">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-4 w-4" fill="none"
viewBox="0 0 24 24">
@@ -175,7 +176,27 @@
</div>
</template>
<template v-else>
<!-- Режим: Кнопка связи с менеджером -->
<template v-else-if="settings.product_interaction_mode === 'manager'">
<button
class="btn btn-primary btn-lg w-full shadow-md"
:disabled="!settings.manager_username"
@click="openManagerChat"
>
<template v-if="settings.manager_username">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-5.74.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/>
</svg>
Связаться с менеджером
</template>
<template v-else>Менеджер недоступен</template>
</button>
</template>
<!-- Режим: Открытие товара на сайте -->
<template v-else-if="settings.product_interaction_mode === 'browser'">
<button
class="btn btn-primary btn-lg w-full shadow-md"
:disabled="! product.share"
@@ -301,6 +322,27 @@ function openProductInMarketplace() {
window.Telegram.WebApp.openLink(product.value.share, {try_instant_view: false});
}
function openManagerChat() {
if (!settings.manager_username) {
return;
}
window.Telegram.WebApp.HapticFeedback.selectionChanged();
// Формируем ссылку для открытия чата с менеджером
// manager_username должен быть username (например, @username)
const managerUsername = String(settings.manager_username).trim();
// Если username начинается с @, убираем @
const username = managerUsername.startsWith('@')
? managerUsername.substring(1)
: managerUsername;
const chatUrl = `https://t.me/${username}`;
window.Telegram.WebApp.openTelegramLink(chatUrl);
}
function setQuantity(newQuantity) {
quantity.value = newQuantity;
window.Telegram.WebApp.HapticFeedback.selectionChanged();